zoukankan      html  css  js  c++  java
  • Servlet文件上传和下载的复习

    上传

    使用Servlet完成上传和下载相较于使用Struts框架有点麻烦,毕竟更偏底层了

    项目中主要使用的jar包:

    commons-io-2.2.jar  commons-fileupload-1.3.2.jar

    其他使用的jar有:

    commons-beanutils-1.8.3.jar commons-logging-1.1.1.jar itcast-tools-1.4.2.jar

    页面:

    <body>
    <form action="<c:url value='/uploadServlet3'/>" method="POST" enctype="multipart/form-data">
      照 片:<input type="file" name="zhaopian"/><br/>
    <input type="submit" value="提交"/>
    </form>

    值得注意的是:form要使用post提交,并使用enctype,这和使用Struts的页面要求是一致的

    上传文件四步骤
     1.创建工厂(DiskFileItemFactory)
     2.根据工厂创建解析器(ServletFileUpload)
     3.解析request,得到FileItem集合
     4.遍历FileItem,调用其API完成操作

    我将文件保存在WEB-INF中,这样的话通过浏览器是直接访问不到这个资源的,在WEB-INF中还使用了根据文件名的哈希名称前两个首字母生成目录来存放,对了,这个文件名还用了UUID值+_+文件名的方式避免同名问题,对于部分浏览器可能出现据对路径的问题也进行了处理

    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import cn.itcast.commons.CommonUtils;
    
    public class UploadServlet3 extends HttpServlet {
        
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
        
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            try {
                //前三步
                //DiskFileItemFactory factory=new DiskFileItemFactory();
                //可以使用临时目录(d:/temp需先创建)和设置缓存大小(20kb)
                DiskFileItemFactory factory=new DiskFileItemFactory(20*1024,new File("d:/temp"));
                ServletFileUpload fileUpload=new ServletFileUpload(factory);
                List<FileItem> list = fileUpload.parseRequest(req);
                
                FileItem fi1 = list.get(1);
                //得到文件保存的路径(files目录需创建)
                String root = this.getServletContext().getRealPath("/WEB-INF/files/");
                //处理绝对路径问题
                String fileName=fi1.getName();
                int index=fileName.lastIndexOf("//");
                if(index!=-1){
                    fileName=fileName.substring(index+1);
                }
                
                //处理重名问题
                String saveFileName=CommonUtils.uuid()+"_"+fileName;
                
                //目录打散
                //1.获得文件名的哈希值并转换为十六进制
                int hashCode = fileName.hashCode();
                String hex = Integer.toHexString(hashCode);
                //2.获得十六进制的前两位,生成目录链
                File dirFile=new File(root,hex.charAt(0)+"/"+hex.charAt(1));
                dirFile.mkdirs();
                //3.创建文件并保存
                File desFile=new File(dirFile,saveFileName);
                fi1.write(desFile);
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }
    
    }

    这里使用了CommonUtils类来生成UUID值,这个类是在itcast-tools-1.4.2.jar(传智播客提供)

    下载

    下载所使用的jar包是:commons-io-2.2.jar

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.URLEncoder;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.commons.io.IOUtils;
    import sun.misc.BASE64Encoder;
    
    public class DownloadServlet extends HttpServlet {
    
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            /*
             * 文件下载,两个头一个流
             * 响应头1:Content-Type
             * 响应头2:Content-Disposition
             * 流:下载文件数据
             */
            String fileName="e:/IBelieve.mp3";     //文件所在位置
            String frameName=filenameEncoding("%IBelieve%.mp3", req);  //下载时显示的文件名
            String contentType=this.getServletContext()
                    .getMimeType(fileName);    //通过文件名得到MIME类型
            String contentDisposition="attachment;filename="+frameName;
            //一个流
            FileInputStream inputStream=new FileInputStream(fileName);
            //设置头
            resp.setHeader("Content-Type", contentType);
            resp.setHeader("Content-Disposition", contentDisposition);
            //获取绑定了响应端的流
            ServletOutputStream outputStream=resp.getOutputStream();
            
            IOUtils.copy(inputStream, outputStream);   //将输入流的数据写到输出流
            
            inputStream.close();
            
        }
        
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
        
        //用来对下载文件名进行编码
        public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException {
            String agent = request.getHeader("User-Agent"); //获取浏览器
            if (agent.contains("Firefox")) {
                BASE64Encoder base64Encoder = new BASE64Encoder();
                filename = "=?utf-8?B?"
                        + base64Encoder.encode(filename.getBytes("utf-8"))
                        + "?=";
            } else if(agent.contains("MSIE")) {
                filename = URLEncoder.encode(filename, "utf-8");
            } else {
                filename = URLEncoder.encode(filename, "utf-8");
            }
            return filename;
        }
    }

    filenameEncoding()方法可以根据浏览器的不同对下载的文件名进行编码,避免乱码

  • 相关阅读:
    当年的笔记_apache配置虚拟主机
    sqlserver 调优(三)
    bat命令自用其(一)
    Always On主辅延迟相关描述
    sqlserver中常用的windows命令行的操作
    mysql复制以及一主多从等常见集群概述
    sqlserver 调优(二)
    sqlserver 获取实例上用户数据库的数据字典
    sqlserver事务隔离小结
    mysql 慢查询的小结
  • 原文地址:https://www.cnblogs.com/lz2017/p/7090859.html
Copyright © 2011-2022 走看看