在Java中通过HTTP Get下载文件

5

我已经编写了一个下载Servlet,根据messageID参数返回文件。下面是doGet方法。

    @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    // This messageID would be used to get the correct file eventually
    long messageID = Long.parseLong(request.getParameter("messageID"));
    String fileName = "C:\\Users\\Soto\\Desktop\\new_audio1.amr";
    File returnFile = new File(fileName);


    ServletOutputStream out = response.getOutputStream();
    ServletContext context = getServletConfig().getServletContext();
    String mimetype = context.getMimeType("C:\\Users\\Soto\\Desktop\\new_audio1.amr");

    response.setContentType((mimetype != null) ? mimetype : "application/octet-stream");
    response.setContentLength((int)returnFile.length());
    response.setHeader("Content-Disposition", "attachment; filename=\"" + "new_audio.amr" + "\"");

    FileInputStream in = new FileInputStream(returnFile);
    byte[] buffer = new byte[4096];

    int length;
    while((length = in.read(buffer)) > 0) {
        out.write(buffer, 0, length);
    }
    in.close();
    out.flush();
}

我随后编写了一些代码来检索文件。

String url = "http://localhost:8080/AudioFileUpload/DownloadServlet";
    String charset = "UTF-8";

    // The id of the audio message requested
    String messageID = "1";

    //URLConnection connection = null;


    try {   
        String query = String.format("messageID=%s", URLEncoder.encode(messageID, charset));
        //URLConnection connection;
        //URL u = new URL(url + "?" + query);

        //connection = u.openConnection();
        //InputStream in = connection.getInputStream();

        HttpClient httpClient = new DefaultHttpClient();
        httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);


        HttpGet httpGet = new HttpGet(url + "?" + query);
        HttpResponse response = httpClient.execute(httpGet);

        System.out.println(response.getStatusLine());

        InputStream in = response.getEntity().getContent();

        FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\Soto\\Desktop\\new_audio2.amr"));

        byte[] buffer = new byte[4096];
        int length; 
        while((length = in.read(buffer)) > 0) {
            fos.write(buffer, 0, length);
        }
        //connection = new URL(url + "?" + query).openConnection();
        //connection.setRequestProperty("Accept-Charset", charset);

        //InputStream response = connection.getInputStream();

    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

现在这段代码可以正常工作。我可以下载音频文件并且它可以正确地运行。我想知道的是,如果可能的话,如何获取下载的文件名而不是给它一个我自己的名字。此外,是否有可能获得文件而无需从流中读取(也许有些库可以替你完成)?我有点想隐藏一些肮脏的东西。
谢谢

您可以通过 Content-disposition 条目指定任何您想要的文件名。 - KV Prajapati
请查看commons-io,使用IOUtils来帮助处理流。 - Steven
我该如何从客户端应用程序中获取它?我需要解析头文件吗? - Sotirios Delimanolis
看起来你正在使用commons-http。 Commons-http已经有一个API用于访问HTTP头,这应该会帮助你。 - Steven
我研究了一下,虽然头部信息很棒,但我真正想做的是提取响应体中的内容,即音频文件,而不必逐字节地进行。 - Sotirios Delimanolis
2个回答

1

要在Servlet代码中设置下载文件名,请在响应对象上执行以下操作

 response.setHeader("Content-disposition",
                  "attachment; filename=" +
                  "new_audio1.amr" );

编辑: 我看到你已经在做了。只需尝试删除您添加的斜杠即可。


0

有附件时,文件将以提供的名称正确地提供。当内联时,浏览器似乎会忽略文件名,并且通常在保存内联内容时给出URL的servletname部分作为默认名称。

如果适用,您可以尝试将该URL映射到适当的文件名。

这里有一个相关的SO问题:使用正确的文件名在浏览器内安全下载文件

您可能还会发现这个链接有用:Inline Content-Disposition的文件名属性毫无意义吗?

我认为您不能在没有流的情况下下载文件。对于I/O,必须使用流。


谢谢你的回答,但我无法将其映射到文件名样式的URL,因为文件取决于客户端知道的唯一ID。我可以让文件在名称中包含它们的ID,但我不能保证它总是如此。至于I/O,如果是这种情况,那就太糟糕了。 - Sotirios Delimanolis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接