美文网首页
文件上传下载

文件上传下载

作者: MyTamakiAkoo | 来源:发表于2019-03-12 08:31 被阅读0次

    文件上传下载

    文件上传

    文件上传的应用
    比如个人信息的管理,上传头像
    比如商品信息的管理,上传商品的图片
    这些都需要通过浏览器客户端将图片上传到服务器的磁盘上

    文件上传原理

    所谓的文件上传就是服务器端通过request对象获取输入流,将浏览器端上传的数据读取出来,保存到服务器端

    客户端浏览器注意事项

    • 请求方式必须是 post
    • 需要使用组件<input type="file" name="file">
    • 表单必须设置enctype="multipart/form-data"
      服务器端处理 通过request对象,获取InputStream, 可以将浏览器提交的所有数据读取到.

    上传开源框架-commons-upload

    Apache 开源组织提供了一个用来处理表单文件上传的一个开源组件( Commons-fileupload),该组件性能优异,并且其API使用极其简单,可以让开发人员轻松实现web文件上传功能,因此在web开发中实现文件上传功能,通常使用Commons-fileupload组件实现。

    使用Commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:Commons-fileupload和commons-io, commons-io 不属于文件上传组件的开发jar文件,但Commons-fileupload 组件从1.1版本开始,它工作时需要commons-io包的支持jar包路径:

    保存一个完整的表单信息,除了将文件上传到服务器以外,还需要将其他表单项信息保存到对象,并存储到数据中心,而对应的图片信息则保存为保存的路径即可。
    那么怎么获取到其他的表单项数据?item.getFileName(),item.getString()
    为了更好完成对其他表单项的值的获取,需要借助另一个开源框架 BeanUtils
    它除了自身的jar包,还依赖于commons-logging.jar

    所需要的包

    文件上传案例

    image
    image
    image
    image

    上传单个图片到磁盘

    <body>
         <!-- enctype: 编码类型,提交的表单为二进制内容:multipart/form-data
                        默认为文本编码类型: application/x-www-form-urlencoded
              注意: 表单中的参数就不能通过getParameter去取值了, 要想取表单中的值需要第三方jar包解析    ;
                        但是action属性中的参数是可获取到的     
          -->
         <form action="RegisterServlet?action=upload" method="post" enctype="multipart/form-data">
            
            用户名:<input type="text" name="username" /><br/>
            密码:<input type="text" name="password" /><br/>
            文件上传:<input type="file" name="file" /><br/>
            <input type="submit" value="提交" />
         </form>
    </body>
    
    //版本1:解析图片,存储到D:/b.jpg
        private void deal1(HttpServletRequest request) throws IOException, FileNotFoundException {
            String action = request.getParameter("action");
            if("upload".equals(action)){
                
                //1. 实例化文件上传的工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
                
                //2.从工厂中获取fileUpload的对象
                ServletFileUpload fileUpload = new ServletFileUpload(factory);
                
                //3.通过fileUpload对象解析request
                try {
                    //解析request后,将内容放入第三方提供的FileItem实体类中
                    List<FileItem> list = fileUpload.parseRequest(request);
                    //遍历集合,取出FileItem实体类中的数据
                    for(FileItem fileItem : list){
                        //System.out.println(fileItem);  //打印FileItem实体类对象
                        //判断是否为文本表单内容
                        if(!fileItem.isFormField()){  //处理非文本表单内容---处理图片
                            
                            //-------io流操作-------
                            InputStream iStream = fileItem.getInputStream();
                            int len;
                            byte[] b = new byte[1024];
                            FileOutputStream fos = new FileOutputStream("d://"+fileItem.getName());
                            while((len=iStream.read(b))!=-1){
                                fos.write(b, 0, len);
                            }
                            //----------关流s----------
                            iStream.close();
                            fos.close();
                        }
                    }
                    
                    
                } catch (FileUploadException e) {
                    e.printStackTrace();
                }
                
            }
        }
    

    优化版

    //版本2:io流的优化;图片的路径要跟着项目走--不能随意指定:d:/a.jpg
        private void deal2(HttpServletRequest request) throws IOException, FileNotFoundException {
            String action = request.getParameter("action");
            if("upload".equals(action)){
                
                //1. 实例化文件上传的工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
                
                //2.从工厂中获取fileUpload的对象
                ServletFileUpload fileUpload = new ServletFileUpload(factory);
                
                //3.通过fileUpload对象解析request
                    try {
                        List<FileItem> list = fileUpload.parseRequest(request);
                        for(FileItem fileItem : list){
                            if(!fileItem.isFormField()){  
                                //图片的路径要跟着项目走--不能随意指定:d:/a.jpg
                                //io流的优化
                                
                                //获取的是项目的部署路径下的upload
                                String path = getServletContext().getRealPath("upload");
                                //判断部署的upload路径是否存在,如果不存在则创建
                                File parent = new File(path);
                                if(!parent.exists()){
                                    parent.mkdirs();   //创建父目录
                                }
                                
                                //拼完整图片的文件路径
                                File allFile = new File(parent, fileItem.getName());
                                
                                
                                //------------io流操作:第三方处理-----------
                                //参数1:上传的文件资源
                                IOUtils.copy(fileItem.getInputStream(), new FileOutputStream(allFile));
                            }
                        }
                        
                    } catch (FileUploadException e) {
                        e.printStackTrace();
                    }
            }
        }
    

    解决重名的问题

    //版本3:处理文件上传的重名问题?  uuid,时间
        private void deal3(HttpServletRequest request) throws IOException, FileNotFoundException {
            String action = request.getParameter("action");
            if("upload".equals(action)){
                
                //1. 实例化文件上传的工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
                
                //2.从工厂中获取fileUpload的对象
                ServletFileUpload fileUpload = new ServletFileUpload(factory);
                
                //3.通过fileUpload对象解析request
                
                List<FileItem> list;
                try {
                    list = fileUpload.parseRequest(request);
                    for(FileItem fileItem : list){
                        if(!fileItem.isFormField()){  
                            //图片的路径要跟着项目走--不能随意指定:d:/a.jpg
                            //io流的优化
                            
                            //获取的是项目的部署路径下的upload
                            String path = getServletContext().getRealPath("upload");
                            
                            //处理日期
                            SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/HH/mm/ss");
                            String strDate = sdf.format(new Date());
                            
                            //判断部署的upload路径是否存在,如果不存在则创建
                            File parent = new File(path+strDate);
                            if(!parent.exists()){
                                parent.mkdirs();   //创建父目录
                            }
                            
                            //--处理重命名方式1: uuid
                            //String uuid = UUID.randomUUID().toString();
                            //String fileName = uuid+"_"+fileItem.getName();
                            //File allFile = new File(parent, fileName);
                            
                            //处理重命名方式2: 日期处理: 2019/3/11/11/38/56/a.jpg  2019/3/11/11/38/57/a.jpg
                            File allFile = new File(parent, fileItem.getName());
                            
                            IOUtils.copy(fileItem.getInputStream(), new FileOutputStream(allFile));
                        }
                    }
                    
                } catch (FileUploadException e) {
    
                    e.printStackTrace();
                }
                        
            }
        }
    

    上传文件并使用BeanUtils保存checkbox表单

    <body>
         <!-- enctype: 编码类型,提交的表单为二进制内容:multipart/form-data
                        默认为文本编码类型: application/x-www-form-urlencoded
              注意: 表单中的参数就不能通过getParameter去取值了, 要想取表单中的值需要第三方jar包解析    ;
                        但是action属性中的参数是可获取到的     
          -->
         <form action="RegisterServlet?action=upload" method="post" enctype="multipart/form-data">
            
            用户名:<input type="text" name="username" /><br/>
            密码:<input type="text" name="password" /><br/>
            爱好:<input type="checkbox" name="loves" value="eat" />吃
                <input type="checkbox" name="loves"  value="drink"/>喝
                <input type="checkbox" name="loves"  value="play"/>玩<br/>
            文件上传:<input type="file" name="file" /><br/>
            <input type="submit" value="提交" />
         </form>
    </body>
    
        //版本4:在后台存储完整数据
        private void deal4(HttpServletRequest request)
                throws UnsupportedEncodingException, IOException, FileNotFoundException {
            //1. 实例化文件上传的工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            
            //2.从工厂中获取fileUpload的对象
            ServletFileUpload fileUpload = new ServletFileUpload(factory);
            
            //3.通过fileUpload对象解析request
            
            List<FileItem> list;
            User user = new User();
            Map<String, String> map = new HashMap<>();
            try {
                list = fileUpload.parseRequest(request);
                for(FileItem fileItem : list){
                    if(fileItem.isFormField()){  //处理文本表单内容
                        
                        //获取到map集合中key对应的值,如果为空,则进行存储;否则,进行与旧值拼接
                        String value = map.get(fileItem.getFieldName());
                        if(value == null){
                            map.put(fileItem.getFieldName(), fileItem.getString("utf-8"));
                        }else{
                            map.put(fileItem.getFieldName(), value+","+fileItem.getString("utf-8"));
                        }
                        
                        
                    }else{    //处理二进制内容
                        //获取的是项目的部署路径下的upload
                        String path = getServletContext().getRealPath("upload");
                        
                        //判断部署的upload路径是否存在,如果不存在则创建
                        File parent = new File(path);
                        if(!parent.exists()){
                            parent.mkdirs();   //创建父目录
                        }
                        
                        //--处理重命名方式1: uuid
                        String uuid = UUID.randomUUID().toString();
                        String fileName = uuid+"_"+fileItem.getName();
                        File allFile = new File(parent, fileName);
                        
                        IOUtils.copy(fileItem.getInputStream(), new FileOutputStream(allFile));
                        
                        //user.setUrl(allFile.getAbsolutePath());  //存储图片路径
                    }
                }
                
            } catch (FileUploadException e) {
    
                e.printStackTrace();
            }
            //将map的数据注入的User对象,["username":"zs","password":"123"]
            try {
                BeanUtils.populate(user, map);
                
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    

    展示单个图片、展示多个图片

        //版本5:展示单个图片、展示多个图片
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String action = request.getParameter("action");
            if("upload".equals(action)){
                
                DiskFileItemFactory factory = new DiskFileItemFactory();
                ServletFileUpload fileUpload = new ServletFileUpload(factory);
                
                List<FileItem> list;
                User user = new User();
                Map<String, String> map = new HashMap<>();
                try {
                    list = fileUpload.parseRequest(request);
                    for(FileItem fileItem : list){
                        if(fileItem.isFormField()){  //处理文本表单内容
                            
                            //获取到map集合中key对应的值,如果为空,则进行存储;否则,进行与旧值拼接
                            String value = map.get(fileItem.getFieldName());
                            if(value == null){
                                map.put(fileItem.getFieldName(), fileItem.getString("utf-8"));
                            }else{
                                map.put(fileItem.getFieldName(), value+","+fileItem.getString("utf-8"));
                            }
                            
                            
                        }else{    //处理二进制内容
                            //获取的是项目的部署路径下的upload
                            String path = getServletContext().getRealPath("upload");
                            
                            //判断部署的upload路径是否存在,如果不存在则创建
                            File parent = new File(path);
                            if(!parent.exists()){
                                parent.mkdirs();   //创建父目录
                            }
                            
                            //--处理重命名方式1: uuid
                            String uuid = UUID.randomUUID().toString();
                            String fileName = uuid+"_"+fileItem.getName();
                            File allFile = new File(parent, fileName);
                            
                            IOUtils.copy(fileItem.getInputStream(), new FileOutputStream(allFile));
                            
                            //注意:此处不能存带盘符的完整路径;应该存相对路径
                            //user.setUrl(allFile.getAbsolutePath());  //存储图片路径
                            //需求1: 存储单张图片路径
                            //user.setUrl("upload"+File.separator+fileName);  //File.separator 获取路径符号
                            //需求2: 存储多张图片路径
                            user.getUrList().add("upload"+File.separator+fileName);
                        }
                    }
                    
                } catch (FileUploadException e) {
    
                    e.printStackTrace();
                }
                //将map的数据注入的User对象,["username":"zs","password":"123"]
                try {
                    BeanUtils.populate(user, map);
                    
                    request.setAttribute("urls", user.getUrList());
                    request.getRequestDispatcher("show2.jsp").forward(request, response);
                    
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
                        
            }
        }
    

    文件下载

    主要实现方式有两种

    1.  超链接下载
    2.  以超链接的方式下载压缩文件
    3.  以超链接的方式下载图片文件
    4.  以超链接的方式下载中文文件名的文件
    5.  Servlet下载
    

    有些超链接搞不定的事情就交给Servlet来搞定

    采用流的方式来读和写

    设置响应的头部信息

    response.setHeader("Content-disposition", "attachment;fileName="+fileName);
    细节:

    下载的文件名是中文怎么办?

    代码

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
          <!-- 英文路径直接下载 -->
          <a href="download/b.jpg">下载b.jpg</a><br/>
          <a href="download/b.rar">下载b.rar</a><br/>
          
          <!-- 带中文路径 -->
          <a href="DownloadServlet?path=download/高圆圆.rar">下载高圆圆.rar</a><br/>
    </body>
    </html>
    
    package com.qf.servlet;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.URLEncoder;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.io.IOUtils;
    
    public class DownloadServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String path = request.getParameter("path");
            path = new String(path.getBytes("iso-8859-1"), "utf-8");  //download/高圆圆.jar
            
            //注意: 往往上传或下载的图片名不要有中文,且不要以数字开头
            
            //获取文件名
            String fileName = path.substring(path.indexOf("/")+1);
            
            //将中文文件名进行转码,类似cookie应用
            fileName = URLEncoder.encode(fileName, "utf-8");
            
            //设置响应的头部信息
            response.setHeader("Content-disposition", "attachment;fileName="+fileName);
            
            //注意:io流的读写,是针对完整路径
            path = getServletContext().getRealPath(path);
            //通过第三方方式写出去
            IOUtils.copy(new FileInputStream(path), response.getOutputStream());
        }
    
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    

    总结:

    1. 文件上传案例:
       1. 导入jar包:Commons-fileupload和commons-io
       2. 客户端的操作:
            1.表单的请求方式:method=post
            2.设置enctype=multipart/form-data
            3.控件类型: type="file"
       3. 服务器端的操作:
            1.创建DiskFileItemFactory
            2.创建ServletFileUpload
            3.通过ServletFileUpload的parseRequest方法得到所有的FileItem   
        4.  遍历集合中的所有FileItem对象
            判断如果为非文本表单内容,则将该图片通过io流方式取出
    2. 文件上传操作及优化----版本升级
       1. 获取到FileItem对象后,取出io流内容----先读后写
       2. 存储图片路径跟着项目走(存到部署目录下);第三方io操作优化
       3. 处理文件名重名问题:  加前缀uuid、加入时间目录
       4. 存储完整表单数据: 文本表单、二进制数据等
             建立实体类---存图片时,只需存图片路径即可  
                                   存文本表单时,需通过第三方jar包去注入
             导入jar包:    BeanUtils、commons-logging.jar                        
        存复选框数据时,如何存?
        判断map集合中是否存储该key,如果有则拼接;   
       5、存单张图片、存多张图片(实体类中要有集合的属性用于存url路径)
    3. 文件的下载:
       1.简单的图片下载可以通过超链接直接下载即可  
       2.如果超链接下载不了(例如中文图片名);通过servlet去处理
       servlet处理步骤: 获取到图片路径
                       get请求的转码
                                          提取图片的文件名用于设置头部信息,且仍需转码
                                          通过io流进行下载: IOUtils.copy                 
    

    other

    写相对路径报错


    image
    image

    然后


    image
    说明web项目和java项目还是有区别的 image

    [站外图片上传中...(image-7b84af-1552350602309)]


    image

    .

    相关文章

      网友评论

          本文标题:文件上传下载

          本文链接:https://www.haomeiwen.com/subject/sgwwpqtx.html