JavaWeb篇:文件上传与下载

1、文件的上传介绍

        1、要有一个form标签,method=post请求

        2、form标签的encType属性值必须为multipart/form-data

        3、早form标签中使用input type=file添加上传的文件

        4、编写服务器代码(Servlet程序)接收,处理上传的数据

        encType=multipart/form-data表示提交的数据,以多段(每一个表单一个数据段)的形式进行拼接,然后以二进制的形式发送非服务器

1.1、文件上传,HTTP协议的说明

JavaWeb篇:文件上传与下载

1.2 、commons-fileupload.jar 常用API介绍说明

commons-fileupload.jar要依赖commons-io.jar这个包,所以需导入两个包

第一步,需要导入两个jar包:

        commons-fileupload-1.2.1.jar

        commons-io-1.4.jar

      

commons-fileupload.jar 和commons-io.jar包中常用的类

ServletFileUpload类,用于解析上传的数据

FileItem类,表示每一个表单项

boolean ServletFileUpload.isMultipartContent(HttpServletRequest request);

        判断当前上传的数据格式是否是多段的格式

public List<FileItem> parseRequest(HttpServletRequest request)

        解析上传的数据

Boolean FileItem.isFormField()

        判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。

        true 表示普通类型的表单项

        false表示上传的文件类型

String FileItem.getFieldName()

        获取表单项的文件类型

String FileItem.getFieldName()

        获取表单项的name属性值

String FileItem.getString()

        获取当前表单项的值。

String FileItem.getName();

        获取上传的文件名

void FileItem.write(file);

        将上传的文件写到参数file所指向的硬盘位置。

1.3、fileupload类库的使用:

上传文件的表单

public class Servlet3 extends HttpServlet{
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //1 判断上传的数据是否多段数据(只有多段的数据,才是文件上传的)
        if(ServletFileUpload.isMultipartContent(req)){
            ServletFileUpload servletFileUpload = null;
            List<FileItem> list = null;
            try {
                //创建FileItemFactory工厂实现类
                FileItemFactory factory = new DiskFileItemFactory();
                //创建用于解析上传数据的工具类ServletFileUpload类
                servletFileUpload = new ServletFileUpload(factory);
                //解析上传数据,得到每一个表单项FileItem
                list = servletFileUpload.parseRequest(req);
            //循环判断,表单项是普通类型还是文件
                for(FileItem f : list){
                    if (f.isFormField()){
                        System.out.println("表单项的name属性值:" + f.getFieldName());
                        System.out.println("表单项的value属性值:" + f.getString("UTF-8"));
                    } else {
                        System.out.println("表单项的name属性值:" + f.getFieldName());
                        System.out.println("文件名:" + f.getName());
                        f.write(new File("G:\\" + f.getName()));
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2、文件下载

下载的常用API说明:

response.getOutPutStream();

servletContext.getResourceAsStream();

servletContext.getMimeType();

response.setContenType();

response.setHeader("Content-Disposition","attachment;fileName=1.jpg);

这个响应头告诉浏览器。这是需要下载的。而attachment表示附件,也就是下载的一个文件。fileName=后面,表示下载的文件名。

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取下载的文件名
    String downloadFileName = "2.jpg";
    //2. 读取要下载的文件名(通过ServletContext对象可以读取)
    ServletContext servletContext = getServletContext();
    //获取要下载的文件类型
    String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
    System.out.println("下载的文件类型" + mimeType);
    //4. 在回传输,通过响应头告诉客户端返回的数据类型
       req.setContentType(mimeType);
    //5.还要告诉客户端接收到的数据是用于下载使用(还是使用响应头)
    //content-Disposition响应头,表示收到的数据怎么处理
    //filename表示指定下载的文件名
    resp.setHeader("Content.Disposition","attachment;filename=文件名");

    /**
    *斜杠被服务器解析表示地址为http://ip:port/工程名/映射 到代码的web目录
    */
    InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadName);

    OutputStream outputStream = resp.getOutStream();

        //3. 把下载的文件内容回传给客户端
        //读取输入流中全部的数据,复制给输出流,输出给客户端

    IOUtils.copy(resourceAsStream,outputStream );

    }

但是上面的步骤无法正确显示出中文名。

        原因在响应头中,不能包块中文字符,只能包含ASCLL码。

附件中文名乱码问题解决方案:

方案一:URLEncoder 解决 IE 和谷歌浏览器的 附件中

文名问题。

如果客户端浏览器是 IE 浏览器 或者 是谷歌浏览器。我们需要使用 URLEncoder 类先对中文名进行 UTF-8 的编码

操作。

因为 IE 浏览器和谷歌浏览器收到含有编码后的字符串后会以 UTF-8 字符集进行解码显示。

// 把中文名进行 UTF-8 编码操作。

String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8");

// 然后把编码后的字符串设置到响应头中

response.setHeader("Content-Disposition", str);

方案二:BASE64 编解码 解决 火狐浏览器的附件中文名问

如果客户端浏览器是火狐浏览器。 那么我们需要对中文名进行 BASE64 的编码操作。

这时候需要把请求头 Content-Disposition: attachment; filename=中文名

编码成为:Content-Disposition: attachment; filename==?charset?B?xxxxx?=

=?charset?B?xxxxx?= 现在我们对这段内容进行一下说明。

=?

charset

B

xxxx

?=BASE64 编解码操作:

因为火狐使用的是 BASE64 的编解码方式还原响应中的汉字。所以需要使用 BASE64Encoder 类进行编码操作。

// 使用下面的格式进行 BASE64 编码后

String str = "attachment; fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode("中文.jpg".getBytes("utf-8")) + "?=";

// 设置到响应头中

response.setHeader("Content-Disposition", str);

那么我们如何解决上面两种不同编解码方式呢。我们只需要通过判断请求头中 User-Agent 这个请求头携带过来的

浏览器信息即可判断出是什么浏览器。

如下:

String ua = request.getHeader("User-Agent");

//

判断是否是火狐浏览器

if (ua.contains("Firefox")) {

// 使用下面的格式进行 BASE64 编码后

String str = "attachment; fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode("中文.jpg".getBytes("utf-8")) + "?=";

// 设置到响应头中

response.setHeader("Content-Disposition", str);

} else {

// 把中文名进行 UTF-8 编码操作。

String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8");

// 然后把编码后的字符串设置到响应头中

response.setHeader("Content-Disposition", str);

}

上一篇:java的web实现文件的上传和下载的详情


下一篇:JavaWeb编程基础简单题目