J'ai une exigence où je dois télécharger un PDF à partir du site Web. Le PDF doit être généré dans le code, ce que je pensais être une combinaison de freemarker et d'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?
Réponses:
D'une manière générale, quand vous l'avez
response.getOutputStream()
, vous pouvez y écrire n'importe quoi. Vous pouvez passer ce flux de sortie comme un endroit pour mettre le PDF généré sur votre générateur. De plus, si vous savez quel type de fichier vous envoyez, vous pouvez définirla source
IOUtils
lieu de SpringFileCopyUtils
?J'ai pu diffuser cette ligne en utilisant le support intégré de Spring avec son ResourceHttpMessageConverter. Cela définira la longueur et le type de contenu s'il peut déterminer le type MIME
la source
Content-Disposition
tête de cette façon?Vous devriez pouvoir écrire le fichier directement sur la réponse. Quelque chose comme
puis écrivez le fichier sous forme de flux binaire
response.getOutputStream()
. N'oubliez pas de faireresponse.flush()
à la fin et cela devrait le faire.la source
@RequestMapping(value = "/foo/bar", produces = "application/pdf")
Avec Spring 3.0, vous pouvez utiliser l'
HttpEntity
objet de retour. Si vous l'utilisez, votre contrôleur n'a pas besoin d'unHttpServletResponse
objet et il est donc plus facile à tester. Sauf ceci, cette réponse est relative égale à celle d'Infeligo .Si la valeur de retour de votre framework pdf est un tableau d'octets (lisez la deuxième partie de ma réponse pour d'autres valeurs de retour) :
Si le type de retour de votre PDF Framework (
documentBbody
) n'est pas déjà un tableau d'octets (et également nonByteArrayInputStream
), il serait sage de NE PAS en faire un tableau d'octets en premier. Au lieu de cela, il vaut mieux utiliser:InputStreamResource
,PathResource
(depuis le printemps 4.0) ouFileSystemResource
,exemple avec
FileSystemResource
:la source
return new ResponseEntity<byte[]>(documentBody, headers, HttpStatus.CREATED)
ResponseEntity
est une sous-classe deHttpEntity
(mais je comprends) d'autre part, 201 CREATED n'est pas ce que j'utiliserais lorsque je retournerais juste une vue des données. (voir w3.org/Protocols/rfc2616/rfc2616-sec10.html pour 201 CREATED )Si vous:
byte[]
avant de l'envoyer à la réponse;InputStream
;@ControllerAdvice
exceptions pour vous (ou non).Le code ci-dessous est ce dont vous avez besoin:
À propos de la partie de la longueur du fichier :
File#length()
devrait être assez bonne dans le cas général, mais j'ai pensé que je ferais cette observation car elle peut être lente , auquel cas vous devriez l'avoir stockée précédemment (par exemple dans la base de données). Les cas peuvent être lents: si le fichier est volumineux, spécialement si le fichier est dans un système distant ou quelque chose de plus élaboré comme ça - une base de données, peut-être.InputStreamResource
Si votre ressource n'est pas un fichier, par exemple si vous récupérez les données de la base de données, vous devez utiliser
InputStreamResource
. Exemple:la source
FileSystemResource
là - bas. Il est même conseillé si votre ressource est un fichier . Dans cet exemple,FileSystemResource
peut être utilisé oùInputStreamResource
est.File#length()
devrait être suffisant dans le cas général. Je viens de le mentionner car il peut être lent , surtout si le fichier se trouve dans un système distant ou quelque chose de plus élaboré comme ça - une base de données, peut-être?. Mais ne vous inquiétez que si cela devient un problème (ou si vous avez des preuves tangibles, il le deviendra), pas avant. Le point principal est: vous faites un effort pour diffuser le fichier, si vous devez tout précharger avant, alors le streaming finit par ne faire aucune différence, hein?Ce code fonctionne très bien pour télécharger un fichier automatiquement à partir du contrôleur de printemps en cliquant sur un lien sur jsp.
la source
Le code ci-dessous a fonctionné pour moi pour générer et télécharger un fichier texte.
la source
Ce à quoi je peux penser rapidement, c'est de générer le pdf et de le stocker dans webapp / Downloads / <RANDOM-FILENAME> .pdf à partir du code et d'envoyer un transfert vers ce fichier en utilisant HttpServletRequest
ou si vous pouvez configurer votre résolveur de vue quelque chose comme,
puis reviens
la source
La solution suivante fonctionne pour moi
la source
quelque chose comme ci-dessous
Vous pouvez afficher le PDF ou télécharger des exemples ici
la source
Si cela aide quelqu'un. Vous pouvez faire ce que la réponse acceptée par Infeligo a suggéré mais il suffit de mettre ce bit supplémentaire dans le code pour un téléchargement forcé.
la source
Cela peut être une réponse utile.
Est-il possible d'exporter des données au format pdf en frontend?
S'étendant à cela, l'ajout de disposition de contenu en tant que pièce jointe (par défaut) téléchargera le fichier. Si vous voulez le voir, vous devez le mettre en ligne.
la source
Dans mon cas, je génère un fichier à la demande, il faut donc également générer une URL.
Pour moi, ça fonctionne comme ça:
Très important est le type mime
produces
et aussi, ce nom du fichier fait partie du lien, vous devez donc l'utiliser@PathVariable
.Le code HTML ressemble à ça:
Où
${file_name}
est généré par Thymeleaf dans le contrôleur et c'est-à-dire: result_20200225.csv, de sorte que le lien entier derrière l'URL est:example.com/aplication/dbreport/files/result_20200225.csv
.Après avoir cliqué sur le navigateur de lien me demande quoi faire avec le fichier - enregistrer ou ouvrir.
la source