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 wäre. Gibt es einen besseren Weg?
Mein Hauptproblem ist jedoch, wie ich dem Benutzer erlaube, eine Datei über einen Spring Controller herunterzuladen.
Antworten:
Im Allgemeinen
response.getOutputStream()
können Sie dort alles schreiben , wenn Sie haben . Sie können diesen Ausgabestream als Speicherort für generierte PDF-Dateien an Ihren Generator übergeben. Wenn Sie wissen, welchen Dateityp Sie senden, können Sie auch festlegenquelle
IOUtils
anstelle von Spring zu verwendenFileCopyUtils
?Ich konnte dies mithilfe der im Frühjahr integrierten Unterstützung mit dem ResourceHttpMessageConverter optimieren. Dadurch werden die Inhaltslänge und der Inhaltstyp festgelegt, wenn der MIME-Typ bestimmt werden kann
quelle
Content-Disposition
Header auf diese Weise festzulegen?Sie sollten in der Lage sein, die Datei direkt in die Antwort zu schreiben. Etwas wie
und schreiben Sie die Datei dann als Binär-Stream auf
response.getOutputStream()
. Denken Sie daran,response.flush()
am Ende zu tun, und das sollte es tun.quelle
@RequestMapping(value = "/foo/bar", produces = "application/pdf")
Mit Spring 3.0 können Sie das
HttpEntity
Rückgabeobjekt verwenden. Wenn Sie dies verwenden, benötigt Ihr Controller keinHttpServletResponse
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) :
Wenn der Rückgabetyp Ihres PDF Framework (
documentBbody
) noch kein Byte-Array ist (und auch kein NeinByteArrayInputStream
), ist es ratsam , es NICHT zuerst zu einem Byte-Array zu machen. Stattdessen ist es besser zu verwenden:InputStreamResource
,PathResource
(seit Frühjahr 4.0) oderFileSystemResource
,Beispiel mit
FileSystemResource
:quelle
return new ResponseEntity<byte[]>(documentBody, headers, HttpStatus.CREATED)
ResponseEntity
ist eine Unterklasse vonHttpEntity
(aber ich verstehe) andererseits 201 CREATED ist nicht das, was ich verwenden würde, wenn ich nur eine Ansicht zu den Daten zurückgeben würde. (siehe w3.org/Protocols/rfc2616/rfc2616-sec10.html für 201 CREATED)Wenn du:
byte[]
bevor Sie sie an die Antwort senden.InputStream
;@ControllerAdvice
Ausnahmen für Sie (oder nicht).Der folgende Code ist genau das, was Sie brauchen:
Über den Teil mit der Dateilänge :
File#length()
sollte im allgemeinen Fall gut genug sein, aber ich dachte, ich würde diese Beobachtung machen, weil es langsam sein kann. In diesem Fall sollten Sie es vorher gespeichert haben (z. B. in der Datenbank). Zu den Fällen, in denen es langsam sein kann, gehören: Wenn die Datei groß ist, insbesondere wenn sich die Datei in einem Remote-System befindet oder etwas Ähnlicheres - vielleicht eine Datenbank.InputStreamResource
Wenn Ihre Ressource keine Datei ist, z. B. wenn Sie die Daten aus der Datenbank abrufen, sollten Sie sie verwenden
InputStreamResource
. Beispiel:quelle
FileSystemResource
dort zu benutzen . Es ist sogar ratsam, wenn Ihre Ressource eine Datei ist . In diesem BeispielFileSystemResource
kann verwendet werden, woInputStreamResource
ist.File#length()
sollte im allgemeinen Fall gut genug sein. Ich habe es gerade erwähnt, weil es langsam sein kann , besonders wenn sich die Datei in einem Remote-System befindet oder so etwas Ausgefeilteres - vielleicht eine Datenbank?. Aber machen Sie sich nur Sorgen, wenn es zu einem Problem wird (oder wenn Sie harte Beweise dafür haben, dass es eines wird), nicht vorher. Der Hauptpunkt ist: Sie bemühen sich, die Datei zu streamen. Wenn Sie sie vorher vorab laden müssen, macht das Streaming keinen Unterschied, oder?Dieser Code funktioniert einwandfrei, um eine Datei automatisch von Spring Controller herunterzuladen, wenn Sie auf einen Link auf jsp klicken.
quelle
Der folgende Code hat für mich funktioniert, um eine Textdatei zu generieren und herunterzuladen.
quelle
Was mir schnell einfällt, ist, das PDF zu generieren und es in webapp / downloads / <RANDOM-FILENAME> .pdf aus dem Code zu speichern und mit HttpServletRequest eine Weiterleitung an diese Datei zu senden
oder wenn Sie Ihren View Resolver so konfigurieren können,
dann kehre einfach zurück
quelle
Die folgende Lösung funktioniert für mich
quelle
so etwas wie unten
Sie können PDF - Anzeige oder es Beispiele Download hier
quelle
Wenn es jemandem hilft. Sie können das tun, was die akzeptierte Antwort von Infeligo vorgeschlagen hat, aber dieses zusätzliche Bit einfach in den Code für einen erzwungenen Download einfügen.
quelle
Dies kann eine nützliche Antwort sein.
Ist es in Ordnung, Daten im Frontend als PDF-Format zu exportieren?
Wenn Sie die Inhaltsdisposition als Anhang hinzufügen (Standard), wird die Datei heruntergeladen. Wenn Sie es anzeigen möchten, müssen Sie es auf Inline setzen.
quelle
In meinem Fall generiere ich eine Datei bei Bedarf, daher muss auch eine URL generiert werden.
Bei mir funktioniert so etwas:
Sehr wichtig ist die Eingabe von MIME
produces
und auch, dass dieser Name der Datei Teil des Links ist, den Sie verwenden müssen@PathVariable
.HTML-Code sieht so aus:
Wo
${file_name}
wird von Thymeleaf im Controller generiert und ist dh: result_20200225.csv, so dass der gesamte URL-Behing-Link lautet :example.com/aplication/dbreport/files/result_20200225.csv
.Nach dem Klicken auf den Link fragt mich der Browser, was ich mit der Datei machen soll - speichern oder öffnen.
quelle