views:

39

answers:

1

I'm using a servlet to download some file from a server to a computer. The servlet handle the MIME type and other thing, then launch the dialog box to what do with the file (open, save, cancel). It works correctly when used in FireFox, but when used with IE6 my file is downloaded, but I got a new window with the url of my servlet and with the 404 error. I'm looking on the web, but didn't find any clue to why.

Here is my code, if it helps:

public void doGet(  HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
// envoi du fichier
BufferedInputStream bIn = null;
BufferedOutputStream bOut = null;
int bytesRead;
byte[] buffer = new byte[2048];
try {
    String nomFichier = <my_filename>;
    // encodage des caractères hors [a-Z, 0-9] pis transformation des espace(+) pour l'URL
    String path = <my_path_to_download> + StringUtils.replace(URLEncoder.encode(nomFichier, "UTF-8"), "+", "%20");

    URL url = new URL(path);
    // Test si le fichier bien présent sur le serveur
    if (((HttpURLConnection) url.openConnection()).getResponseCode() != HttpURLConnection.HTTP_OK) {
        throw new FileNotFoundException();
    }
    bIn = new BufferedInputStream(url.openStream());

    String extension = StringUtils.getFilenameExtension(nomFichier).toLowerCase();
    // choix du type MIME selon l'extension du fichier
    if (Extensions.PDF.equals(extension)) {
        res.setContentType("application/pdf");
    } else if (Extensions.WORD.equals(extension)) {
        res.setContentType("application/msword");
    } else if (Extensions.HTM.equals(extension)) {
        res.setContentType("text/htm");
    } else if (Extensions.HTML.equals(extension)) {
        res.setContentType("text/html");
    } else {
        LOGGER.error("Format de fichier non géré : " + extension);
        throw new RuntimeException("Format de fichier non géré : " + extension);
    }
    // n'ouvre pas dans le navigateur et renseigne le nom de fichier pour "Save as..."
    res.setHeader("Content-Disposition", "attachment; filename=\"" + nomFichier + "\";");

    // lecture/écriture des données
    bOut = new BufferedOutputStream(res.getOutputStream());
    while (-1 != (bytesRead = bIn.read(buffer, 0, buffer.length))) {
        bOut.write(buffer, 0, bytesRead);
    }
} catch (Exception e) {
    LOGGER.error("Erreur à la récupération du fichier " + nomFichier, e.getCause());
    res.sendError(HttpServletResponse.SC_NOT_FOUND);
} finally {
    if (bIn != null)
        bIn.close();
    if (bOut != null)
        bOut.close();
}

}

+1  A: 

Apart from several things which can be done more efficiently (e.g. ServletContext#getMimeType() and so on), the code looks fine (you can if necessary get some ideas from this example).

The problem is clearly more in the client side. It is impossible to get a HTTP (404) response without firing a HTTP request first. The client is apparently firing two HTTP requests to the server side instead of one. One of the possible causes for this is that you've added some Javascript function to the onclick of the link or the button which isn't returning false from it due to some IE6 specific bug in the Javascript code. The other possible cause is that you used target="_blank" in the link or form while that's completely unnecessary for a download link/button. Other cause is that you used Javascript window.open() to fire the download request while that's completely unnecessary as well.

After all just have a "plain vanilla" form whose action points to the servlet or a "plain vanilla" link whose href points to the servlet. The Content-Disposition: attachment header will force the browser to pop a Save As dialogue. Absolutely no Javascript or target attribute is necessary here.

BalusC
Ok, the problem wasn't coming from the servelt, but by the way I was calling the servlet : I was using navigateToUrl (Flex) and so it's opening in a new window.So it was normal that's I have a problem, cause it was empty, and so it was FF which wasn't acting correctly by closing the new window.We were using the navigateToUrl cause of the new security policy of the FileReference.download() wich didn't like a call indirect... But we have found a work around and now all it's good :)Thank a lot to the answer which direct me in the right way
LE GALL Benoît