454 votes

Téléchargement d’un fichier de contrôleurs de printemps

J'ai besoin de télécharger un fichier PDF sur le site Web, le fichier PDF doit être généré dans le code, ce que je pensais être une combinaison de freemarker et un cadre de génération de PDF comme iText (une meilleure façon?). Cependant, mon principal problème est de savoir comment autoriser l'utilisateur à télécharger un fichier via un contrôleur Spring.

Toutes les idées ou solutions sur la façon d'aborder ce problème sont les bienvenues

Cordialement, Milinda

435voto

Infeligo Points 4923
 @RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
public void getFile(
    @PathVariable("file_name") String fileName, 
    HttpServletResponse response) {
    try {
      // get your file as InputStream
      InputStream is = ...;
      // copy it to response's OutputStream
      org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
      response.flushBuffer();
    } catch (IOException ex) {
      log.info("Error writing file to output stream. Filename was '{}'", fileName, ex);
      throw new RuntimeException("IOError writing file to output stream");
    }

}
 

En règle générale, quand vous avez response.getOutputStream() , vous pouvez écrire n'importe quoi là-bas. Vous pouvez passer ce flux de sortie comme un endroit pour mettre le PDF généré à votre générateur. En outre, si vous connaissez le type de fichier que vous envoyez, vous pouvez définir

 response.setContentType("application/pdf");
 

307voto

Scott Carlson Points 951

J'ai été en mesure de diffuser cette ligne en utilisant le support intégré au printemps avec son ResourceHttpMessageConverter. Cela définira la longueur du contenu et le type de contenu s'il peut déterminer le type mime

 @RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
@ResponseBody
public FileSystemResource getFile(@PathVariable("file_name") String fileName) {
    return new FileSystemResource(myService.getFileFor(fileName)); 
}
 

88voto

lobster1234 Points 4572

Vous devriez être capable d'écrire le fichier sur la réponse directement. Quelque chose comme

 response.setContentType("application/pdf");      
response.setHeader("Content-Disposition", "attachment; filename=somefile.pdf"); 
 

puis écrivez le fichier en tant que flux binaire sur response.getOutputStream() . N'oubliez pas de faire response.flush() à la fin et cela devrait le faire.

83voto

Ralph Points 42744

Avec Spring 3.0, vous pouvez utiliser l'objet de retour HttpEntity . Si vous l'utilisez, votre contrôleur n'a pas besoin d'un objet HttpServletResponse , et par conséquent, il est plus facile à tester. Sauf ceci, cette réponse est relative à celle d'Infeligo .

 @RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET)
public HttpEntity<byte[]> createPdf(
                 @PathVariable("fileName") String fileName) throws IOException {

    byte[] documentBody = this.pdfFramework.createPdf(filename);

    HttpHeaders header = new HttpHeaders();
    header.setContentType(new MediaType("application", "pdf"));
    header.set("Content-Disposition",
                   "attachment; filename=" + fileName.replace(" ", "_"));
    header.setContentLength(documentBody.length);

    return new HttpEntity<byte[]>(documentBody, header);
}
 

81voto

acdcjunior Points 19898

Si vous:

  • Ne voulez pas charger tout le fichier dans un byte[] avant l'envoi de la réponse;
  • Voulez/besoin d'envoyer/télécharger via InputStream;
  • Voulez avoir le plein contrôle de la Mime Type et le nom de fichier envoyé;
  • Avoir d'autres @ControllerAdvice de ramasser des exceptions pour vous.

Le code ci-dessous est ce que vous avez besoin de:

@RequestMapping(value = "/stuff/{stuffId}", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> downloadStuff(@PathVariable int stuffId)
                                                                  throws IOException {
    String fullPath = stuffService.figureOutFileNameFor(stuffId);
    File file = new File(fullPath);

    HttpHeaders respHeaders = new HttpHeaders();
    respHeaders.setContentType("application/pdf");
    respHeaders.setContentLength(12345678);
    respHeaders.setContentDispositionFormData("attachment", "fileNameIwant.pdf");

    InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
    return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
}

Notez également que pour éviter de lire tout le fichier que vous venez de calculer sa longueur, vous feriez mieux de l'avoir stocké précédemment. Assurez-vous de vérifier les docs pour InputStreamResource.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X