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()方法可以根据浏览器的不同对下载的文件名进行编码,避免乱码

posted @ 2017-06-28 17:39  OverZeal  阅读(279)  评论(0编辑  收藏  举报