文件的上传与下载

这篇博客详细介绍了如何使用Java处理文件上传和下载。在文件上传部分,讲解了form表单设置、multipart/form-data的使用以及Apache的commons-fileupload库。在文件下载部分,讨论了Content-Disposition头的设置、文件类型的指定,以及处理中文文件名乱码的问题。同时提供了UpLoadServlet和DownLoadServlet的代码示例。
摘要由CSDN通过智能技术生成

上传文件

基础知识

  1. 要有一个form标签,用于向服务器发送表单数据;form表单的method属性为post。
传送方式数据大小
GET当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。
POST发送数据无限制。
安全性与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET !
  1. form标签的encType 属性值必须为 multipart/form-data 值,encType=multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器。
  2. form标签中的input type=“file” 添加上传的文件。
<form action="/JSTL//uploadImg" method="post" enctype="multipart/form-data">
    <label>用户名:</label><input name="username" placeholder="用户名" type="text"> <br>
    <label>头像:</label><input type="file" name="photo"><br>
    <input type="submit" value="提交">
</form>

依赖包

  • commons-fileupload-1.2.1.jar
  • commons-io-1.4.jar

功能分析

  1. 首先,服务器接收图片的数据是多端传输的,因此判断上传的数据是否为多段传输(只有多段传输数据,才是文件上传的)
    使用ServletFileUpload.isMultipartContent(request)检查数据是否符合传输格式。
  2. 当数据格式符合时,就需要解析接收到的数据。
  3. 对数据进行数据流转换,并保存。

功能实现

  • ServletFileUpload
    org.apache.commons.fileupload.servlet.ServletFileUpload类是Apache文件上传组件处理文件上传的核心高级类(所谓高级就是不需要管底层实现,暴露给用户的简单易用的接口)
ServletFileUpload类构造方法
方法说明
public ServletFileUpload()构造一个未初始化的实例,需要在解析请求之前先调用setFileItemFactory()方法设置 fileItemFactory属性。
public ServletFileUpload(FileItemFactory fileItemFactory)构造一个实例,并根据参数指定的FileItemFactory 对象,设置 fileItemFactory属性。
ServletFileUpload类常用方法
public void setSizeMax(long sizeMax)setSizeMax方法继承自FileUploadBase类,用于设置请求消息实体内容(即所有上传数据)的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。在请求解析的过程中,如果请求消息体内容的大小超过了setSizeMax方法的设置值,将会抛出FileUploadBase内部定义的SizeLimitExceededException异常(FileUploadException的子类)。该方法有一个对应的读方法:public long getSizeMax()方法。
public void setFileSizeMax(long fileSizeMax)setFileSizeMax方法继承自FileUploadBase类,用于设置单个上传文件的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。该方法有一个对应的读方法:public long geFileSizeMax()方法。在请求解析的过程中,如果单个上传文件的大小超过了setFileSizeMax方法的设置值,将会抛出FileUploadBase内部定义的FileSizeLimitExceededException异常(FileUploadException的子类)。
public List parseRequest(javax.servlet.http.HttpServletRequest req)parseRequest 方法是ServletFileUpload类的重要方法,它是对HTTP请求消息体内容进行解析的入口方法。它解析出FORM表单中的每个字段的数据,并将它们分别包装成独立的FileItem对象,然后将这些FileItem对象加入进一个List类型的集合对象中返回。该方法抛出FileUploadException异常来处理诸如文件尺寸过大、请求消息中的实体内容的类型不是“multipart/form-data”、IO异常、请求消息体长度信息丢失等各种异常。每一种异常都是FileUploadException的一个子类型。
public FileItemIterator getItemIterator(HttpServletRequest request)getItemIterator方法和parseRequest 方法基本相同。但是getItemIterator方法返回的是一个迭代器,该迭代器中保存的不是FileItem对象,而是FileItemStream 对象,如果你希望进一步提高新能,你可以采用getItemIterator方法,直接获得每一个文件项的数据输入流,做底层处理;如果性能不是问题,你希望代码简单,则采用parseRequest方法即可。
public stiatc boolean isMultipartContent(HttpServletRequest req)isMultipartContent方法方法用于判断请求消息中的内容是否是“multipart/form-data”类型,是则返回true,否则返回false。isMultipartContent方法是一个静态方法,不用创建ServletFileUpload类的实例对象即可被调用。
getFileItemFactory()和setFileItemFactory(FileItemFactory)方法继承自FileUpload类,用于设置和读取fileItemFactory属性。
public void setProgressListener(ProgressListener pListener)设置文件上传进度监听器。该方法有一个对应的读取方法:ProgressListener getProgressListener()。

判断数据是否为多段传输:

ServletFileUpload.isMultipartContent(request)
  • 解析上传的数据,得到每个表单项FileItem
    将请求消息实体中的每一个项目封装成单独的DiskFileItem (FileItem接口的实现) 对象的任务,由 org.apache.commons.fileupload.FileItemFactory 接口的默认实现org.apache.commons.fileupload.disk.DiskFileItemFactory 来完成。
//创建FileItemFactory工厂实现类  
//public DiskFileItemFactory()     采用默认临界值和系统临时文件夹构造文件项工厂对象。
FileItemFactory fileItemFactory = new DiskFileItemFactory();
         //public ServletFileUpload(FileItemFactory fileItemFactory)	
         //构造一个实例,并根据参数指定的FileItemFactory 对象,设置 fileItemFactory属性。
            
            //创建用于解析上传数据的工具类--ServletFileUpload类
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);

执行成功后,将数据存储到List中并保存数据

UpLoadServlet完整代码

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //判断上传的数据是否为多段传输(只有多穿传输数据,才是文件上传的)
        if (ServletFileUpload.isMultipartContent(request)) {
            //创建FileItemFactory工厂实现类
            FileItemFactory fileItemFactory = new DiskFileItemFactory();
            //创建用于解析上传数据的工具类--ServletFileUpload类
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);

            try {
                //解析上传的数据,得到每个表单项FileItem
                List<FileItem> fileItems = servletFileUpload.parseRequest(request);
                //循环判断每个表单项是普通类型,还是上传的文件
                for (FileItem fileItem : fileItems) {
                    if (fileItem.isFormField()) {
                        //如果是普通表单项
                        System.out.println("表单项的name属性值:" + fileItem.getFieldName());
                        System.out.println("表单项的value属性值:"+fileItem.getString("UTF-8"));
                    } else {
                        //上传的是文件
                        System.out.println("表单项的name属性值:" + fileItem.getFieldName());
                        System.out.println("上传文件名:" + fileItem.getName());
                        fileItem.write(new File("e:\\"+fileItem.getName()));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

文件下载

基础知识

  1. 既然文件要发给客户端进行下载,那么我们首先要告诉客户端要将文件进行下载存储:response.setHeader(“Content-Disposition”,“attachment;filename=”+Filename);
    其中,filename是指定存储文件时的文件名;
  2. 告诉客户端服务器返回的数据的类型:response.setContentType("文件类型“)。
  3. http协议是不支持中文,因此各种浏览器采用的编码格式,火狐使用Base64进行编码,而chorme和IE采用URLEncode进行编码。当编码格式不正确时,http数据将出现乱码,下载文件名包含中文时文件名会出现乱码状况。
  4. 采用servletContext对象对需要传输的文件内容进行读取。
    由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。

废话不多说了,过程和上传文件没太大差别,我们就直接上代码!!

DownLoadServlet完整代码

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取要下载文件的文件名
        String downFileName = "forest.pdf";
        //2.读取要下载的文件的内容(通过servletContext对象可以读取)
        ServletContext servletContext = getServletContext();
        //3.获取要下载的文件的类型
        String mimeType = servletContext.getMimeType("fileOpretion/file/" + downFileName);
        System.out.println("要下载的文件类型为:" + mimeType);
        //4.回传前,通过响应头告诉客户端返回数据的类型
        resp.setContentType(mimeType);
        //5.告诉客户端收到的数据数用于下载的(还是使用响应头)
        //Content-Disposition响应头表示收到的数据怎么处理
            //attachment表示附件,表示下载使用
            //filename = 表示指定下载的文件名
        //火狐浏览器使用Base64进行编码,chorme和IE使用URLEncode进行编码
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("刘.pdf","utf-8"));



        /**
         * "/"被服务器解析为http://ip:port/工程名/
         */
        InputStream resourceAsStream = servletContext.getResourceAsStream("fileOpretion/file/" + downFileName);
        //获取响应的输出流
        OutputStream outputStream = resp.getOutputStream();

        //把下载内容给客户端
        //读取输入流中全部数据,复制给输出流,输出给客户端
        int copy = IOUtils.copy(resourceAsStream, outputStream);

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值