Bonjour,
J'essaye depuis plusieurs jours de réaliser une servlet de téléchargement de fichier depuis un navigateur(Serveur Caucho Resin 3.1.6).
L'utilisateur sélectionne le fichier par le biais d'un moteur de recherche etc...
J'ai deja fait ce genre de servlet plusieurs fois mais je rencontre quelques problèmes de cahier des charges avec ce projet:
- Lorsque l'utilisateur annule le téléchargement (a l'invite de sauvegarde, ou pendant le téléchargement), la boucle d'envoi de ma servlet continue sans fin, pas d'exception(comme je l'aurai espérer), pas de fermeture du flux, rien.
Pas de souci a priori, sauf quand les fichiers a envoyé par le serveur peuvent faire plusieurs centaines de Mo et que plusieurs utilisateurs peuvent télécharger en même temps. Donc l'utilisateur clique sur télécharger, annule , et ma servlet mouline jusqu'à ce qu'elle est transférer tout le contenu du flux du fichier vers le flux (fantôme) de la réponse (sic). D'un point de vue optimisation des ressource c'est une catastrophe.
J'ai sniffer le réseaux avec wireshark , quand l'utilisateur annule, le flux http s'arrête, et le client envoi au serveur un RST ACK (royalement ignoré)
J'ai fait part de ce comportement étrange a mes collègues et ils n'avait jamais réalisé l'existence de ce problème, de même après avoir cherché longuement sur internet j'ai l'impression que personne n'a jamais remarqué cela, ou personne n'a ce problème, ou alors personne ne s'en préoccupe.
Voici le code de ma servlet (sans les traces)
J'ai essayer avec plusieurs type de flux : Buffered, Channel ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 File f; UserFile uf; BinaryFile bf; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); if(getSessionAccess()==null){ resp.sendRedirect("Login"); return; } //TODO logs Download on UserFile, BinaryFile and DownloadLog getFile(req.getParameter("file")); f = new File(bf.getAbsolutePath()); if(!f.exists()){ throw new FileNotFoundException("File not found: "+bf.getId()); } int length = 0; ServletOutputStream sout = resp.getOutputStream(); ServletContext context = getServletConfig().getServletContext(); String mimetype = context.getMimeType( f.getAbsolutePath() ); // Setup the httpResponse resp.reset(); resp.setContentType( (mimetype != null) ? mimetype : "application/octet-stream" ); resp.setBufferSize(10240); resp.setHeader( "Content-Disposition", "attachment; filename=\"" + uf.getUfName() + "\"" ); resp.setContentLength((int)f.length()); // Stream to the requester. byte[] bbuf = new byte[10240]; DataInputStream in = new DataInputStream(new FileInputStream(f)); while ((in != null) && ((length = in.read(bbuf)) != -1)) { try { //Used to slow down file upload , otherwise localhost testing require superhuman speed Thread.sleep(1); } catch (InterruptedException e) { System.err.println("Download interrupted"); } try{ sout.write(bbuf,0,length); sout.flush(); }catch(IOException ioe){ ioe.printStackTrace(); } } in.close(); sout.flush(); sout.close(); //TODO update Downloaded logs }
En désespoir de cause je soupçonne le conteneur d'être responsable de cela, j'ai du mal a admettre que ce soit logique de la part des concepteur qu'une servlet puisse faire un traitement long de ce type pour faire plaisir a un navigateur éteint .
Si vous avez une idée ou un indice qui pourrais m'aidez a avancer je vous en serais très reconnaissant.
Partager