如何在网站中实现下载的功能?——Javaweb

た 入场券 2021-06-22 15:36 518阅读 0赞

文件下载实现

一、概述

下载是什么?
下载其实就是向客户端响应字节数据。
把一个文件变成字节数组,然后使用response.getOutputStream()响应给浏览器。

下载的要求:
下载的要求其实可以简要概括成六个字:“两个头一个流 ”。

  • 两个头:分别为Content-Type和Content-Disposition。
    Content-Type表示的是你传递给客户端的文件的MIME类型,例如:image/pjpeg。可以通过文件名称调用ServletContext.getMimeType()方法,得到MIME类型。
    Content-Disposition的默认值为inline,表示在浏览器窗口中打开。我们要给的值是如下这种格式:attachment;filename=xxx 。在filename=后面跟随的是显示在下载框中的文件名称。
  • 一个流:就是要下载的文件数据。我们自己new一个输入流即可。

二、文件下载的示例

我们新建一个项目,并且创建一个servlet:

  1. public class Download1Servlet extends HttpServlet {
  2. public void doGet(HttpServletRequest request, HttpServletResponse response)
  3. throws ServletException, IOException {
  4. /* * 准备两个头,一个流 * 1. Content-Type * 2. Content-Disposition * 3. 流:下载的文件数据 */
  5. String filename = "E:/test.jpg";
  6. // 两个头
  7. // 通过文件名称获取文件MIME类型
  8. String contentType = this.getServletContext().getMimeType(filename);
  9. String contentDisposition = "attachment;filename=a.jpg";
  10. // 创建一个数据流
  11. FileInputStream input = new FileInputStream(filename);
  12. // 接下来设置头
  13. response.setHeader("Content-Type", contentType);
  14. response.setHeader("Content-Disposition", contentDisposition);
  15. // 获取绑定的客户端的流
  16. ServletOutputStream output = response.getOutputStream();
  17. // 把输入流的东西写入到输出流中
  18. IOUtils.copy(input, output);
  19. input.close();
  20. }
  21. }

我们直接在浏览器中访问这个servlet,我们看一下会有什么结果:
在这里插入图片描述
我们可以看到,弹出了一个另存为的对话框,默认的文件名就是我们设置的a.jpg。

三、有没有什么问题?

我们接着上一个示例,我们做一些更改,把文件的默认名称也就是filename=后面的内容设置为中文,我们看一下会是什么效果。
比如我们更改为:

  1. String contentDisposition = "attachment;filename=测试用图.jpg";

我们在浏览器看一下,会是什么效果:
我们可以看到在谷歌浏览器中,文件是没有显示正确的,只显示了jpg三个字母:
在这里插入图片描述
我们在edge下也是不正确的:
在这里插入图片描述
而在IE(IE 11)也是不正常的:
在这里插入图片描述
这是为什么呢?

原因和解决办法

Firefox浏览器(上面我们并没有使用该浏览器进行测试),使用的是Base64编码。而其他的大部分浏览器,使用的都是URL编码。所以才会出现上面的情况。

我们应该怎么办呢?
其实很简单,我们只需要对文件名字符串进行一个处理,

  1. filename = new String(filename.getBytes("GBK"),"ISO-8859-1");

上面示例的代码,我们就做以下的修改:
在这里插入图片描述
我们再测试一下:
chrome:
在这里插入图片描述

工具类

我们还应该注意一点,因为浏览器的不同,使用的编码方式是不同的。我们应该先获取浏览器的版本信息,然后进行相应的转码。其实我们有一个工具类,代码很简单,如下:

  1. package com.veeja.down.utils;
  2. import java.io.IOException;
  3. import java.io.UnsupportedEncodingException;
  4. import java.net.URLEncoder;
  5. import javax.servlet.http.HttpServletRequest;
  6. import sun.misc.BASE64Encoder;
  7. public class DownUtils {
  8. public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException {
  9. String agent = request.getHeader("User-Agent"); //获取浏览器
  10. if (agent.contains("Firefox")) {
  11. BASE64Encoder base64Encoder = new BASE64Encoder();
  12. filename = "=?utf-8?B?"
  13. + base64Encoder.encode(filename.getBytes("utf-8"))
  14. + "?=";
  15. } else if(agent.contains("MSIE")) {
  16. filename = URLEncoder.encode(filename, "utf-8");
  17. } else {
  18. filename = URLEncoder.encode(filename, "utf-8");
  19. }
  20. return filename;
  21. }
  22. }

这个工具类就可以获取浏览器的版本进行相应的转换。

使用这个工具类,我们再次改写我们以前的代码:
在这里插入图片描述
这样,我们再次测试一下:
在这里插入图片描述
也是完全OK的!


END.

发表评论

表情:
评论列表 (有 0 条评论,518人围观)

还没有评论,来说两句吧...

相关阅读