it-swarm.com.de

Herunterladen einer Datei von Spring Controllern

Ich habe eine Anforderung, bei der ich ein PDF von der Website herunterladen muss. Das PDF muss innerhalb des Codes generiert werden, was meiner Meinung nach eine Kombination aus Freemarker und einem PDF Generierungsframework wie iText ist. Irgendein besserer Weg?

Mein Hauptproblem ist jedoch, wie kann der Benutzer eine Datei über einen Spring Controller herunterladen?

344
MilindaD
@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");
    }

}

Wenn Sie response.getOutputStream() haben, können Sie im Allgemeinen alles dort schreiben. Sie können diesen Ausgabestream als Speicherort übergeben, um generierte PDF an Ihren Generator zu übertragen. Wenn Sie wissen, welchen Dateityp Sie senden, können Sie festlegen

response.setContentType("application/pdf");
367
Infeligo

Ich konnte dies mithilfe der integrierten Unterstützung in Spring mit dem ResourceHttpMessageConverter optimieren. Dadurch werden die Inhaltslänge und der Inhaltstyp festgelegt, wenn der MIME-Typ ermittelt werden kann

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

Sie sollten in der Lage sein, die Datei direkt in die Antwort zu schreiben. So etwas wie

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

und schreibe dann die Datei als binären Stream auf response.getOutputStream(). Denken Sie daran, am Ende response.flush() zu tun, und das sollte es tun.

76
lobster1234

Mit Spring 3.0 können Sie das Rückgabeobjekt HttpEntity verwenden. Wenn Sie dies verwenden, benötigt Ihr Controller kein HttpServletResponse-Objekt und ist daher einfacher zu testen. Abgesehen davon ist diese Antwort relativ gleich der von Infeligo .

Wenn der Rückgabewert Ihres PDF-Frameworks ein Byte-Array ist (lesen Sie den zweiten Teil meiner Antwort für andere Rückgabewerte) :

@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(MediaType.APPLICATION_PDF);
    header.set(HttpHeaders.CONTENT_DISPOSITION,
                   "attachment; filename=" + fileName.replace(" ", "_"));
    header.setContentLength(documentBody.length);

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

Wenn der Rückgabetyp Ihres PDF Frameworks (documentBbody) nicht bereits ein Byte-Array ist (und auch kein ByteArrayInputStream), ist dies der Fall war klug NICHT, es zuerst zu einem Byte-Array zu machen. Stattdessen ist es besser zu verwenden:

beispiel mit FileSystemResource:

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

    File document = this.pdfFramework.createPdf(filename);

    HttpHeaders header = new HttpHeaders();
    header.setContentType(MediaType.APPLICATION_PDF);
    header.set(HttpHeaders.CONTENT_DISPOSITION,
                   "attachment; filename=" + fileName.replace(" ", "_"));
    header.setContentLength(document.length());

    return new HttpEntity<byte[]>(new FileSystemResource(document),
                                  header);
}
72
Ralph

Wenn du:

  • Sie möchten nicht die gesamte Datei in einen byte[] laden, bevor Sie sie an die Antwort senden.
  • Möchten/müssen Sie es senden/herunterladen über InputStream;
  • Sie möchten die vollständige Kontrolle über den Mime-Typ und den gesendeten Dateinamen haben.
  • Lassen Sie andere @ControllerAdvice Ausnahmen für Sie aufgreifen.

Der folgende Code ist was Sie brauchen:

@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);
}

Um zu vermeiden, dass die gesamte Datei nur zur Berechnung der Länge gelesen wird, sollten Sie sie zuvor speichern. Stellen Sie sicher, dass Sie in den Dokumenten nach InputStreamResource suchen.

57
acdcjunior

Dieser Code funktioniert gut, um eine Datei automatisch von Spring Controller herunterzuladen, wenn Sie auf einen Link auf jsp klicken.

@RequestMapping(value="/downloadLogFile")
public void getLogFile(HttpSession session,HttpServletResponse response) throws Exception {
    try {
        String filePathToBeServed = //complete file name with path;
        File fileToDownload = new File(filePathToBeServed);
        InputStream inputStream = new FileInputStream(fileToDownload);
        response.setContentType("application/force-download");
        response.setHeader("Content-Disposition", "attachment; filename="+fileName+".txt"); 
        IOUtils.copy(inputStream, response.getOutputStream());
        response.flushBuffer();
        inputStream.close();
    } catch (Exception e){
        LOGGER.debug("Request could not be completed at this moment. Please try again.");
        e.printStackTrace();
    }

}
18
Sunil

Der folgende Code hat mir beim Generieren und Herunterladen einer Textdatei geholfen.

@RequestMapping(value = "/download", method = RequestMethod.GET)
public ResponseEntity<byte[]> getDownloadData() throws Exception {

    String regData = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
    byte[] output = regData.getBytes();

    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.set("charset", "utf-8");
    responseHeaders.setContentType(MediaType.valueOf("text/html"));
    responseHeaders.setContentLength(output.length);
    responseHeaders.set("Content-disposition", "attachment; filename=filename.txt");

    return new ResponseEntity<byte[]>(output, responseHeaders, HttpStatus.OK);
}
12
Siva Kumar

Was ich mir schnell vorstellen kann ist, das PDF zu generieren und es in der Datei webapp/downloads/<RANDOM-FILENAME> .pdf aus dem Code zu speichern und mit HttpServletRequest an diese Datei weiterzuleiten

request.getRequestDispatcher("/downloads/<RANDOM-FILENAME>.pdf").forward(request, response);

oder wenn Sie Ihren View Resolver konfigurieren können,

  <bean id="pdfViewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass"
              value="org.springframework.web.servlet.view.JstlView" />
    <property name="order" value=”2″/>
    <property name="prefix" value="/downloads/" />
    <property name="suffix" value=".pdf" />
  </bean>

dann kehre einfach zurück

return "RANDOM-FILENAME";
5
kalyan

so etwas wie unten

@RequestMapping(value = "/download", method = RequestMethod.GET)
public void getFile(HttpServletResponse response) {
    try {
        DefaultResourceLoader loader = new DefaultResourceLoader();
        InputStream is = loader.getResource("classpath:META-INF/resources/Accepted.pdf").getInputStream();
        IOUtils.copy(is, response.getOutputStream());
        response.setHeader("Content-Disposition", "attachment; filename=Accepted.pdf");
        response.flushBuffer();
    } catch (IOException ex) {
        throw new RuntimeException("IOError writing file to output stream");
    }
}

Sie können PDF anzeigen oder Beispiele herunterladen hier

2
xxy

Die folgende Lösung funktioniert für mich

    @RequestMapping(value="/download")
    public void getLogFile(HttpSession session,HttpServletResponse response) throws Exception {
        try {

            String fileName="archivo demo.pdf";
            String filePathToBeServed = "C:\\software\\Tomcat 7.0\\tmpFiles\\";
            File fileToDownload = new File(filePathToBeServed+fileName);

            InputStream inputStream = new FileInputStream(fileToDownload);
            response.setContentType("application/force-download");
            response.setHeader("Content-Disposition", "attachment; filename="+fileName); 
            IOUtils.copy(inputStream, response.getOutputStream());
            response.flushBuffer();
            inputStream.close();
        } catch (Exception exception){
            System.out.println(exception.getMessage());
        }

    }
1

Wenn es jemandem hilft. Sie können tun, was die akzeptierte Antwort von Infeligo vorschlägt, aber nur dieses zusätzliche Bit in den Code für einen erzwungenen Download einfügen.

response.setContentType("application/force-download");
0
Sagar Nair