453 Stimmen

Herunterladen einer Datei von Spring Controllern

Ich habe eine Anforderung, bei der ich eine PDF-Datei von der Website herunterladen muss. Das PDF muss innerhalb des Codes generiert werden. Ich dachte, das wäre eine Kombination aus Freemarker und einem PDF-Generierungs-Framework wie iText. Gibt es einen besseren Weg?

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

60voto

Denis Zavedeev Punkte 6644

Do

  1. Rückkehr ResponseEntity<Resource> aus einer Handler-Methode
  2. Geben Sie an. Content-Type
  3. Satz Content-Disposition falls erforderlich:
    1. Dateiname
    2. Typ
      1. inline um die Vorschau in einem Browser zu erzwingen
      2. attachment um einen Download zu erzwingen

Ejemplo

@Controller
public class DownloadController {
    @GetMapping("/downloadPdf.pdf")
    // 1.
    public ResponseEntity<Resource> downloadPdf() {
        FileSystemResource resource = new FileSystemResource("/home/caco3/Downloads/JMC_Tutorial.pdf");
        // 2.
        MediaType mediaType = MediaTypeFactory
                .getMediaType(resource)
                .orElse(MediaType.APPLICATION_OCTET_STREAM);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(mediaType);
        // 3
        ContentDisposition disposition = ContentDisposition
                // 3.2
                .inline() // or .attachment()
                // 3.1
                .filename(resource.getFilename())
                .build();
        headers.setContentDisposition(disposition);
        return new ResponseEntity<>(resource, headers, HttpStatus.OK);
    }
}

Erläuterung

Rückkehr ResponseEntity<Resource>

Wenn Sie eine ResponseEntity<Resource> El ResourceHttpMessageConverter schreibt den Inhalt der Datei

Beispiele für Resource Implementierungen:

Geben Sie an. Content-Type ausdrücklich :

Grund: siehe " FileSystemResource wird mit dem Inhaltstyp json zurückgegeben " Frage

Optionen:

  • Hardcode der Kopfzeile
  • Verwenden Sie die MediaTypeFactory vom Frühling. Die MediaTypeFactory Karten Resource a MediaType unter Verwendung der /org/springframework/http/mime.types Datei
  • Verwenden Sie eine Bibliothek eines Drittanbieters wie Apache Tika

Satz Content-Disposition falls erforderlich :

Über Content-Disposition Kopfzeile:

Der erste Parameter im HTTP-Kontext ist entweder inline (Standardwert, der angibt, dass sie innerhalb der Webseite oder als Webseite angezeigt werden kann) oder attachment (was anzeigt, dass es heruntergeladen werden soll; die meisten Browser zeigen einen "Speichern unter"-Dialog an, der mit dem Wert der Dateinamensparameter vorausgefüllt ist, falls vorhanden).

Utilice ContentDisposition in der Anwendung:

  • An Vorschau eine Datei in einem Browser:

    ContentDisposition disposition = ContentDisposition
            .inline()
            .filename(resource.getFilename())
            .build();
  • Um eine herunterladen :

    ContentDisposition disposition = ContentDisposition
            .attachment()
            .filename(resource.getFilename())
            .build();

Utilice InputStreamResource sorgfältig :

Geben Sie an. Content-Length unter Verwendung der HttpHeaders#setContentLength Methode, wenn:

  1. Die Länge ist bekannt
  2. Sie verwenden InputStreamResource

Der Grund: Der Frühling will nicht schreiben Content-Length para InputStreamResource weil Spring die Länge der Ressource nicht bestimmen kann. Hier ist ein Codeschnipsel aus ResourceHttpMessageConverter :

@Override
protected Long getContentLength(Resource resource, @Nullable MediaType contentType) throws IOException {
    // Don't try to determine contentLength on InputStreamResource - cannot be read afterwards...
    // Note: custom InputStreamResource subclasses could provide a pre-calculated content length!
    if (InputStreamResource.class == resource.getClass()) {
        return null;
    }
    long contentLength = resource.contentLength();
    return (contentLength < 0 ? null : contentLength);
}

In anderen Fällen setzt Spring die Content-Length :

~ $ curl -I localhost:8080/downloadPdf.pdf  | grep "Content-Length"
Content-Length: 7554270

24voto

Sunil Punkte 462

Dieser Code funktioniert gut, um eine Datei automatisch vom Spring Controller herunterzuladen, wenn Sie auf einen Link im 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();
    }

}

20voto

Siva Kumar Punkte 560

Der folgende Code hat bei mir funktioniert, um eine Textdatei zu erzeugen und herunterzuladen.

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

6voto

kalyan Punkte 3047

Was ich schnell denken kann, ist, generieren Sie die PDF und speichern Sie es in webapp/downloads/< RANDOM-FILENAME>.pdf aus dem Code und senden Sie eine Weiterleitung zu dieser Datei mit HttpServletRequest

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

oder wenn Sie Ihren View-Resolver so konfigurieren können wie,

  <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 einfach zurückgeben

return "RANDOM-FILENAME";

4voto

Jorge Santos Neill Punkte 1389

Die folgende Lösung funktioniert bei mir

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

    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X