Java Spring - généré dynamiquement fichier csv télécharger la réponse est suspendu
Sur mon site de l'entreprise, nous avons quelques tables dont nous avons besoin pour exporter vers un fichier csv.
Il y a quelques varier les paramètres, de sorte que le fichier csv doit être créé dynamiquement à la demande.
Mon problème est que après avoir cliqué sur télécharger, la réponse se bloque, et attendre pour l'ensemble du fichier à créer (ce qui peut prendre un certain temps), et seulement ensuite télécharge le fichier entier en un instant.
Je suis en utilisant AngularJS, donc je suis en utilisant window.location = <url_for_file_download>
afin de rendre le navigateur à télécharger le fichier.
Sur le côté serveur, je suis en utilisant Java Spring et j'ai suivi toutes les instructions que j'ai pu trouver sur le web dans le but de créer un fichier de téléchargement contrôleur.
Mon code de contrôleur est quelque chose comme ceci:
@RequestMapping(value = "http://yada.yada.yada/csv/myFile.csv", method = RequestMethod.GET)
public @ResponseBody
void getCustomers(HttpServletResponse response,
@RequestParam(required = false) String someParameters)
throws NotAuthorizedException, IOException {
//set headers
setHeaders(response);
//generate writer
CSVWriter write = generateWriter(response);
//get data
List<String[]> data = getData();
//write and flush and all that
.
.
.
}
Mon code pour le réglage des en-têtes de réponse sont:
response.setContentType("text/csv;charset=utf-8");
response.setHeader("Content-Disposition","attachment; filename=\"" + fileName + ".csv\"");
J'ai aussi essayé d'ajouter les en-têtes suivants:
response.setHeader("Transfer-Encoding", "Chunked");
response.setHeader("Content-Description", "File Transfer");
et j'ai aussi essayé le réglage du type de Contenu pour "application/octet-stream"
.
Avis que je ne suis pas d'ajouter un Content-length
- tête, car le fichier n'existe pas encore, et est en cours d'écriture à la volée.
Pour écrire le fichier csv que je suis en utilisant OpenCSV et mon code est comme suit:
OutputStream resOs = response.getOutputStream();
OutputStream buffOs = new BufferedOutputStream(resOs);
OutputStreamWriter outputWriter = new OutputStreamWriter(buffOs,"UTF-8");
CSVWriter writer = new CSVWriter(outputWriter);
Je itérer sur les données et l'écrire comme ceci:
for (String[] row: data) {
writer.writeNext(line);
}
(Ce n'est pas exactement le code, mais c'est plus ou d'autre ce qui se passe dans le code)
Et à la fin je tire la chasse et de la proximité:
writer.flush();
writer.close();
J'ai aussi essayé de rinçage après chaque ligne que j'écris.
Alors pourquoi n'est-ce pas le fichier en cours de transfert avant qu'il a été écrit?
Pourquoi mon navigateur (Google chrome) en téléchargeant le fichier dans un instant, après une longue attente? Et comment je peux résoudre ce problème.
J'espère que j'ai ajouté assez de code, si il manque quelque chose, juste s'il vous plaît dites-moi et je vais essayer de l'ajouter ici.
Je vous remercie beaucoup à l'avance.
Oui, désolé si ce n'était pas clair. Mais je ne l'utilisation de certains aidant fonctions, que je passe l'objet httpServletResponse, afin de définir les en-têtes et de créer de l'écrivain. Je vais modifier la question.
avez-vous trouvé la solution pour ce problème? Je vais avoir le même.
Non, désolé, je n'ai pas.
vérifier si ma réponse est utile.
OriginalL'auteur jonny bordo | 2015-02-23
Vous devez vous connecter pour publier un commentaire.
Pouvez-vous essayer de retourner une valeur null dans votre java
return null ;
Ou vous pouvez essayer de code ci-dessous également
1. Jquery code en cliquant sur le bouton "soumettre"
Votre code de contrôleur
Espère que cette aide
Une question rapide. Quelle est la taille de votre Fichier csv téléchargé(en mo).À partir de votre post, je comprends que vous tirez sur les données soient téléchargées à partir de DB tables.Ainsi, lorsque vous exécutez cette requête manuellement combien de temps sa prend pour récupérer les enregistrements entiers
C'est la chose, je ne peut pas détecter la taille du fichier en avance, puisque je suis de générer le fichier à la volée. actuellement je travaille avec des petits 200-300 K fichiers, mais dans l'avenir, ils peuvent grandir de MBs. Selon la base de données.
si sa aller au-delà de 20 MO et si vous ne voulez pas que votre INTERFACE utilisateur d'attendre pour l'ensemble de données à traiter et téléchargé , alors je suppose meilleure option est de conclure cette logique dans certains appel Asynchrone(par exemple :Thread).Comme si vous utilisez le fil , vous pouvez envelopper le csv télécharger logique dans la méthode run .De sorte que, une fois que l'utilisateur appuyez sur télécharger bouton csv , la demande sera traitée dans le backend, sans impact sur l'INTERFACE utilisateur de la partie.
Je suppose que je vais avoir à séparer le processus à deux demandes: l'une pour lancer la création du fichier et de l'enregistrer sur un emplacement statique, de retour de l'url, et la seconde pour aller chercher le fichier. Merci pour l'aide de Thomas.
OriginalL'auteur Thomas
Le Contrôleur va attendre la réponse écrite avant que la réponse est renvoyée au client.
Voici un joli post avec de multiples approches et les options décrites
Le téléchargement d'un fichier à partir du printemps contrôleurs
Ce post parle de rinçage de la sortie périodiquement pour aider à fixer le téléchargement.
comment faire pour télécharger de gros fichiers sans problèmes de mémoire en java
Si tout ce que vous essayez de faire est de laisser l'utilisateur de savoir que le fichier de téléchargement est en cours et bientôt, je pense que l'Ajax état d'avancement de la indicaor pourrait être votre solution.
De déclenchement de l'appel ajax pour le back-end pour générer le fichier
Afficher l'indicateur de progression de l'utilisateur tandis que le fichier est généré côté serveur
une fois que la réponse est disponible, le fichier est présenté à l'utilisateur.
Je pense que quelque chose de similaire est en train d'être explorées ici télécharger le fichier avec l'ajax() APRÈS une Demande par Spring MVC
Espérons que cette aide!
Grâce,
Paul
SALUT Johnny, la réponse, une fois engagé ne peut pas être modifié. Votre objectif final est d'essayer et télécharger le fichier plus rapidement droit? Ou vous n'avez absolument besoin pour être en mesure de "une sorte de ruisseau" le fichier?
Salut Paul, mon problème est que le fichier est peut-être grand, et alors il aura à prendre un certain temps à télécharger (je parle de 10 ou peut-être de plusieurs secondes). Mon problème est que parce que le fichier se télécharge instantanément, il n'y a pas d'indication pour l'utilisateur que le fichier a été demandé. C'est pourquoi je veux écouter le fichier, il va commencer tout de suite, et l'utilisateur de voir le progrès dans le navigateur de la page de téléchargement.
comment au sujet de l'appel au serveur un appel ajax, puis en montrant à l'utilisateur un indicateur de progrès, tandis que son attente de la réponse du serveur.
Merci pour la réponse de Paul. Je ne peux pas exactement télécharger le fichier avec une requête ajax, mais j'ai peut vraiment suffit de diviser en deux demandes: l'une pour lancer la création du fichier, et un autre pour récupérer le fichier à partir d'un emplacement statique.
OriginalL'auteur Paul John
J'ai fait face à la même question. Le code qui ne fonctionne pas pour moi a été
Le coupable était
ShallowEtagHeaderFilter
. Lorsque ce filtre est activé, la réponse est envoyée dans un gros morceau. Lorsque ce filtre est activée, la réponse est de l'envoyer en plusieurs morceaux.De ce fil Tomcat ne pas vider le tampon de réponse il ressemble à un autre coupable possible peut être
GzipFilter
OriginalL'auteur medvedev1088