Servlet de téléchargement (Resin)
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 8O , 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)
Code:
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
} |
J'ai essayer avec plusieurs type de flux : Buffered, Channel ...
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.