Téléchargement de fichier à l'aide de RichFaces
On m'a déjà travailler:
- Utilisateur peut télécharger un fichier (c'est à dire une archive compressée)
- Utilisateur peut décompresser le fichier sur le serveur
- Utilisateur peut exécuter des trucs sur ces fichiers, ce qui donne plus de fichiers à créer
Maintenant, j'ai besoin d'obtenir de l'étape 4 à l'œuvre:
- L'utilisateur peut télécharger les fichiers sur son propre ordinateur à nouveau
Quelqu'un peut me donner un indice? J'ai essayé de comprendre les trucs que j'ai trouvé sur Google, mais il ne fonctionne pas tout à fait comme prévu. Dois-je définir un type de contenu? Lorsque j'ai mis en application/octet stream uniquement les fichiers csv et txt affiche correctement (dans le navigateur, ne pas télécharger de pop-up que je voulais) d'autres fichiers de travail...
JSP:
<a4j:commandLink value="Download" action="#{appController.downloadFile}" rendered="#{!file.directory}">
<f:param name="file" value="#{file.absoluteFilename}" />
</a4j:commandLink>
appController:
public String downloadFile() {
String filename = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("file");
File file = new File(filename);
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
writeOutContent(response, file, file.getName());
FacesContext.getCurrentInstance().responseComplete();
return null;
}
private void writeOutContent(final HttpServletResponse res, final File content, final String theFilename) {
if (content == null) {
return;
}
try {
res.setHeader("Pragma", "no-cache");
res.setDateHeader("Expires", 0);
res.setHeader("Content-disposition", "attachment; filename=" + theFilename);
FileInputStream fis = new FileInputStream(content);
ServletOutputStream os = res.getOutputStream();
int bt = fis.read();
while (bt != -1) {
os.write(bt);
bt = fis.read();
}
os.flush();
fis.close();
os.close();
} catch (final IOException ex) {
Logger.getLogger(ApplicationController.class.getName()).log(Level.SEVERE, null, ex);
}
}
Vous devez vous connecter pour publier un commentaire.
Concrètement, votre problème est que vous avez tenté de télécharger des fichiers par de l'Ajax. Ce n'est pas correct. JavaScript ne peut pas traiter avec le binaire réponses ne les installations de forcer un Enregistrer sous dialogue. Vous avez besoin de faire un normal synchrone demande au lieu de cela, de sorte que c'est le navigateur lui-même qui a à traiter avec elle.
Comme pour le réglage du type de contenu, si vous avez un nom de fichier avec l'extension lors de vos mains, vous pouvez utiliser
ServletContext#getMimeType()
à résoudre sur la base<mime-mapping>
dansweb.xml
(soit par défaut du serveur ou votre webapp est une).(note que je suppose que vous êtes en utilisant JSF 1.x, en voyant la façon dont vous avez obtenu la réponse de servlet, vous pouvez depuis JSF 2.x par ailleurs également utiliser
ExternalContext#getMimeType()
)J'ai fait l'étape 4 il y a quelques semaines, et laissez-moi vous donner quelques conseils:
Utiliser un lien balise html composant. Pour cela, je vous recommande le
a4j:htmlCommandLink
étiquette de composant (c'est comme le communh:commandLink
avec la différence que le<f:param />
composants sont toujours rendus, vous pouvez vérifier plus dans le la documentation du composant).Si vous ne connaissez pas le type de fichier à télécharger (les), vous devez définir le Contenu application/octet-stream.
Après la configuration, le fichier à télécharger pour votre réponse, vous devez définir que la réponse a été achevé.
Je vais mettre mon Backing Bean code pour cette demande:
La jsp fragment que j'ai utilisé ressemble à ceci:
Espère que cela vous aide.
EDIT: j'ai eu un peu de temps, désolé, mais nous sommes un peu occupé dans le projet. Le code Java a été mis à jour et testé avec IE8, Firefox 9 et 10, et Chrome 16. Pour la valeur de la taille de la mémoire tampon constant, j'ai fait quelques recherches et trouvé une bonne réponse dans cette site.
P. S.: je ne prends pas cela comme une compétition, j'essaie juste d'aider les gens quand je le peux. Si mon code n'est pas bon alors merci de me laisser savoir, c'est la meilleure façon pour tout le monde à mieux se développer, et en bonne santé :).
EDIT: Merci à @lisa
À atteindre les objectifs suivants manuellement, en changeant simplement de la présente partie à l'extrait de
objFileInputStream.available()
ne fait pas ce que vous pensez que cela fonctionne...byte[]
s comme ceci lien de montre.Vous n'avez pas besoin de richfaces a4j:commandLink balise pour le téléchargement, le standard de la balise jsf h:commandLink serait suffisant.
Alors assurez-vous d'avoir les en-têtes suivants mis à votre réponse (vous pouvez vérifier avec firebug dans firefox):
Content-Length: nombre d'octets.