J'essaie de télécharger un fichier. L'action est déclenchée par ajax () Post Request. La demande envoie des données au format JSON au contrôleur. Le contrôleur génère le fichier (octets) et le renvoie.
Script Java:
function getLicenseFile() {
$.ajax({
type: 'POST',
url: '<%=request.getContextPath()%>/licenses/rest/downloadLicenseFile',
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: ko.mapping.toJSON(licenseModel),
success: function (data) {
console.log("in sucess")
},
error:function (xhr, ajaxOptions, thrownError){
console.log("in error")
}
});
}
Manette:
@RequestMapping(value = "/licenses/rest/downloadLicenseFile", method = RequestMethod.POST)
@ResponseStatus(value=HttpStatus.OK)
@ResponseBody
public void createLicenseFile(@Valid @RequestBody License license, HttpServletResponse response) throws Exception {
logger.debug("Contoller License in: "+ license);
byte[] licensedata = licenseEncodeDefaultService.createLicenseFile(license);
logger.debug("licenseData: " + new String(licensedata));
response.setHeader("Content-Disposition", "attachment; filename=\"" + license.getCustomer() + ".license\"");
response.getOutputStream().write(licensedata);
response.flushBuffer();
}
Problème:
* Le navigateur devrait ouvrir une boîte de téléchargement, mais cela ne se produira pas
* La réponse est gérée dans l'erreur: section de la fonction ajax (mais l'état http est OK)
Alors qu'est-ce que je fais mal ou quelle est la bonne façon de faire cela?
Envoyez simplement une URL du fichier en réponse, puis "visitez" celle-ci dans votre rappel success
.
function getLicenseFile() {
$.ajax({
type: 'POST',
url: '<%=request.getContextPath()%>/licenses/rest/downloadLicenseFile',
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: ko.mapping.toJSON(licenseModel),
success: function (data) {
window.open(data.fileUrl);
// or window.location.href = data.fileUrl;
},
error:function (xhr, ajaxOptions, thrownError) {
console.log("in error");
}
});
}
data.fileUrl
doit être défini en réponse par le serveur pour indiquer au client où obtenir le fichier.
Donc, votre serveur enverra une réponse avec JSON comme
{
"fileUrl": "http://mysite.com/files/0123456789"
}
@ will824 Si vous le demandez, je vais poster ma propre solution.
J'ai utilisé une solution de contournement dans le contrôleur et enregistrer temporairement le fichier dans le système de fichiers (/ tmp). Je sépare la fonction en 2 étapes. Créer et télécharger ... Ceci n’est pas très gentil mais me convient assez bien.
Contrôleur (créer un fichier, sera sauvegardé sur le système de fichiers du serveur):
@RequestMapping(value = "/licenses/rest", method = RequestMethod.PUT)
@ResponseStatus(value=HttpStatus.OK)
@ResponseBody
public String createLicenseFile(@Valid @RequestBody License license) throws Exception {
// create encrypted license file and send the name back to view
String fileName = licenseEncodeDefaultService.createLicenseFile(license);
return fileName;
}
Contrôleur (fichier à télécharger):
@RequestMapping(value = "/licenses/downloadFile/{file}", method = RequestMethod.GET)
public void downloadLicenseFile(@PathVariable("file") String file, HttpServletResponse response) throws Exception {
// create full filename and get input stream
File licenseFile = new File ("/tmp/" + file);
InputStream is = new FileInputStream(licenseFile);
// set file as attached data and copy file data to response output stream
response.setHeader("Content-Disposition", "attachment; filename=\"" + file + ".license\"");
FileCopyUtils.copy(is, response.getOutputStream());
// delete file on server file system
licenseFile.delete();
// close stream and return to view
response.flushBuffer();
}
javascript:
function getLicenseFile() {
//console.log(ko.mapping.toJSON(licenseModel));
$.ajax({
type : 'PUT',
url : '${pageContext.request.contextPath}/licenses/rest',
dataType : 'text',
contentType : 'application/json;charset=UTF-8',
data : ko.mapping.toJSON(licenseModel),
success : function(data) {
window.location.href = '${pageContext.request.contextPath}/licenses/downloadFile/'
+ data;
},
error : function(xhr, ajaxOptions, thrownError) {
// error handling
}
});
}
Si vous souhaitez télécharger le fichier sans modifier l'URL, vous pouvez appeler form.submit () par programme à la place en utilisant ajax.
Javascript:
function downloadFileUsingForm(url) {
var form = document.createElement("form");
form.method = "post";
form.action = url;
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
downloadFileUsingForm("/YourController/DownloadFile");
Manette:
[HttpPost]
public ActionResult DownloadFile()
{
string content = "Some Values";
byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes(content);
return File(bytes, System.Net.Mime.MediaTypeNames.Application.Octet, "file.txt");
}
Comme les commentaires l'ont dit, vous ne pouvez pas le faire avec un appel ajax, mais vous pouvez le faire avec Javascript.
function getLicenseFile() {
var downloadUrl = "${pageContext.request.contextPath}/licenses/rest/downloadLicenseFile";
// (optionally) provide the user with a message that the download is starting
window.location.href = downloadUrl;
}
Notez l'utilisation de ${pageContext.request.contextPath}
, qui est préférable à <%=request.getContextPath()%>
.
Ajax ne va pas vous aider à essayer avec l'approche de la forme cachée
<form action='../servletname' method='POST' id='formid'>
<input type='hidden' value='' name='name' id='id'/>
<input type='hidden' value=' ' name='name' id='id' />
</form>
passez votre mot de passe via le champ de formulaire en cliquant sur votre bouton de téléchargement
$ ('# formidable'). submit ();
puis côté serveur
response.setContentType("application/vnd.ms-Excel");
response.setHeader("Content-Disposition", "attachment; filename=filnemae.fileformat");
ServletOutputStream out = res.getOutputStream();
écrire sur le flux de sortie puis fermer ou rincer
si vous envoyez des données volumineuses via post update postsize dans server.xml