zoukankan      html  css  js  c++  java
  • 20160420javaweb之文件上传和下载

    一、文件上传
    1.提供表单允许用户通过表单选择文件进行上传
    表单必须是POST提交
    文件输入框必须有name属性,只有有name属性的输入项浏览器才会进行提交
    需要设置enctype属性值为multipart/form-data

    POST /Day15/upload.jsp HTTP/1.1
    Accept: text/html, application/xhtml+xml, */*
    Referer: http://localhost/Day15/upload.jsp
    Accept-Language: zh-CN
    User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
    Content-Type: multipart/form-data; boundary=---------------------------7de1e62806e0
    Accept-Encoding: gzip, deflate
    Host: localhost
    Content-Length: 394
    Connection: Keep-Alive
    Cache-Control: no-cache
    Cookie: JSESSIONID=818C14110CA7BFD1FC90610866A220E8

    -----------------------------7de1e62806e0
    Content-Disposition: form-data; name="description1"

    xxxx
    -----------------------------7de1e62806e0
    Content-Disposition: form-data; name="description2"

    zzzz
    -----------------------------7de1e62806e0
    Content-Disposition: form-data; name="file1"; filename="ip.txt"
    Content-Type: text/plain

    192
    -----------------------------7de1e62806e0--

    2.在Servlet中将上传的文件保存在服务器的硬盘中
    DiskFileItemFactory
    public DiskFileItemFactory(int sizeThreshold, java.io.File repository)

    public DiskFileItemFactory()
    public void setSizeThreshold(int sizeThreshold) --用来设定内存缓冲区的大小,默认是10k
    public void setRepository(java.io.File repository) --设定临时文件夹的大小

    ServletFileUpload
    boolean isMultipartContent(HttpServletRequest request) 判断上传表单是否为multipart/form-data类型
    List parseRequest(HttpServletRequest request) 解析request对象,并把表单中的每一个输入项包装成一个fileItem 对象,并返回一个保存了所有FileItem的list集合。
    setFileSizeMax(long fileSizeMax) 设置单个上传文件的最大值
    setSizeMax(long sizeMax) 设置上传文件总量的最大值
    setHeaderEncoding(java.lang.String encoding) 设置编码格式,解决上传文件名乱码问题
    setProgressListener(ProgressListener pListener) 实时监听文件上传状态

    FileItem
    boolean isFormField() 判断FileItem是一个文件上传对象还是普通表单对象
    示例代码:

    <%@ 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>
    <h1>文件上传</h1><hr>
    <form action="${pageContext.request.contextPath }/UploadFileServlet" method="post" enctype="multipart/form-data">
         描述信息1:<input type="text" name="description1"/>
           描述信息2:<input type="text" name="description2"/>
           <input type="file" name="file1"/>
           <input type="submit" value="上传"/>
    </form>
    </body>
    </html>
    package com.dzq.web;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    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.FileUploadException;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    import com.dzq.utils.IOUtils;
    
    
    @WebServlet("/UploadFileServlet")
    public class UploadFileServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
       
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            /*InputStream is=request.getInputStream();
            byte[] bs=new byte[1024];
            int i=0;
            while((i=is.read(bs))!=-1){
                System.out.write(bs,0,i);
            }
            is.close();*/
            
            try {
                //1.创建工厂
                DiskFileItemFactory factory =new DiskFileItemFactory();
                //2.生产文件上传核心类
                ServletFileUpload fileupload=new ServletFileUpload(factory);
                //3.利用文件上传核心类解析request
                List<FileItem> list=fileupload.parseRequest(request);
                //4.遍历所有的fileitem
                for(FileItem item:list){
                    if(item.isFormField()){
                        //当前是普通字段项
                        String name=item.getFieldName();
                        String value=item.getString();
                        System.out.println(name+":"+value);
                    }else{
                        //当前是一个文件上传项
                        String filename=item.getName();
                        InputStream in=item.getInputStream();
                        OutputStream out=new FileOutputStream(this.getServletContext().getRealPath("/upload"+filename));
                        IOUtils.In2Out(in, out);
                        IOUtils.close(in, out);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    package com.dzq.utils;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    public class IOUtils {
       private IOUtils(){
           
       }
       
       public static void In2Out(InputStream in,OutputStream out) throws IOException{
           byte[] bs=new byte[1024];
           int i=0;
           while ((i=in.read(bs))!=-1) {
            out.write(bs,0,i);
        }
       }
       
       public static void close(InputStream in,OutputStream out){
           if(in!=null){
               try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                in=null;
            }
           }
           
           if(out!=null){
               try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                out=null;
            }
           }
       }
    }


    如果是一个普通字段项可以调用:
    String getFieldName() 获得普通表单对象的name属性
    String getString(String encoding) 获得普通表单对象的value属性,可以用encoding进行编码设置

    如果是一个文件上传项:
    String getName() 获得上传文件的文件名(有些浏览器会携带客户端路径)
    InputStream getInputStream() 获得上传文件的输入流
    delete() 在关闭FileItem输入流后,删除临时文件



    文件存放应该注意的问题:
    1.upload文件夹和temp文件夹都要放在web-inf目录下保护起来,防止上传入侵和访问其他用户上传资源的问题
    2.文件名要拼接uuid保证唯一
    3.文件要分目录存储保证同一目录下不要有过多的文件,分目录的算法有很多,介绍了一种根据hash值分目录算法

    文件上传的一些细节:

    package com.itheima.web;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.math.BigDecimal;
    import java.util.List;
    import java.util.UUID;
    
    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.ProgressListener;
    import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    import com.itheima.util.IOUtils;
    
    public class UploadServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
            try{
                //1.创建工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
                factory.setSizeThreshold(100*1024);
                factory.setRepository(new File(this.getServletContext().getRealPath("WEB-INF/temp")));
                //2.生产文件上传核心类
                ServletFileUpload fileUpload = new ServletFileUpload(factory);
                
                //--检查是否是正确的文件上传表单
                if(!fileUpload.isMultipartContent(request)){
                    throw new RuntimeException("请用正确的表单进行上传!");
                }
                //--设置文件上传的大小限制
    //            fileUpload.setFileSizeMax(1024*1024*100);//单个文件不大于10M
    //            fileUpload.setSizeMax(1024*1024*100);//总大小不大于100M
                
                //--设置编码集,解决上传文件名的乱码问题
                fileUpload.setHeaderEncoding("utf-8");
                
                //--设置文件上传监听
                fileUpload.setProgressListener(new ProgressListener(){
                    Long beginTime = System.currentTimeMillis();
                    public void update(long bytesRead, long contentLength, int items) {
                        BigDecimal br = new BigDecimal(bytesRead).divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
                        BigDecimal cl = new BigDecimal(contentLength).divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
                        System.out.print("当前读取的是第"+items+"个上传项,总大小"+cl+"KB,已经读取"+br+"KB");
                        //剩余字节数
                        BigDecimal ll = cl.subtract(br);
                        System.out.print("剩余"+ll+"KB");
                        //上传百分比
                        BigDecimal per = br.multiply(new BigDecimal(100)).divide(cl,2,BigDecimal.ROUND_HALF_UP);
                        System.out.print("已经完成"+per+"%");
                        //上传用时
                        Long nowTime = System.currentTimeMillis();
                        Long useTime = (nowTime - beginTime)/1000;
                        System.out.print("已经用时"+useTime+"秒");
                        //上传速度
                        BigDecimal speed = new BigDecimal(0);
                        if(useTime!=0){
                            speed = br.divide(new BigDecimal(useTime),2,BigDecimal.ROUND_HALF_UP);
                        }
                        System.out.print("上传速度为"+speed+"KB/S");
                        //大致剩余时间
                        BigDecimal ltime = new BigDecimal(0);
                        if(!speed.equals(new BigDecimal(0))){
                            ltime = ll.divide(speed,0,BigDecimal.ROUND_HALF_UP);
                        }
                        System.out.print("大致剩余时间为"+ltime+"秒");
                        
                        System.out.println();
                    }
                    
                });
                
                //3.利用文件上传核心类解析request
                List<FileItem> list = fileUpload.parseRequest(request);
                //4.遍历所有的FileItem
                for(FileItem item : list){
                    if(item.isFormField()){
                        //当前是一个普通的字段项
                        String name = item.getFieldName();
                        String value = item.getString("utf-8");
                        System.out.println(name+":"+value);
                    }else{
                        //当前是一个文件上传项
                        String filename = item.getName();
                        String uuidName = UUID.randomUUID().toString()+"_"+filename;
                        
                        int hash = uuidName.hashCode();
                        String hashStr = Integer.toHexString(hash);
                        char [] hss = hashStr.toCharArray();
                        String path = this.getServletContext().getRealPath("WEB-INF/upload");
                        for(char c : hss){
                            path+="/"+c;
                        }
                        new File(path).mkdirs();
                        
                        InputStream in = item.getInputStream();
                        OutputStream out = new FileOutputStream(new File(path,uuidName));
                        
                        IOUtils.In2Out(in, out);
                        IOUtils.close(in, out);
                        
                        //--删除临时文件
                        item.delete();
                    }
                }
            }catch (FileSizeLimitExceededException e) {
                response.getWriter().write("单个文件不超过10M,总大小不超过100M!");
                return;
            }catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    
        
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    
    }

    二、文件下载
    response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename,"utf-8"));
    response.setContentType(this.getServletContext().getMimeType(filename));//MIME类型

    下载示例源码:

    package com.dzq.web;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URLEncoder;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.dzq.utils.IOUtils;
    
    
    @WebServlet("/DownServlet")
    public class DownServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
       
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1.获取要下载的资源的名称
        
             String filename = request.getParameter("file");
            response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename,"utf-8"));
            response.setContentType(this.getServletContext().getMimeType(filename));//MIME类型
            
            InputStream in = new FileInputStream(this.getServletContext().getRealPath("/"+filename));
            OutputStream out = response.getOutputStream();
            IOUtils.In2Out(in, out);
            IOUtils.close(in, null);
            //2.读取资源
            
        }
    
        
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
  • 相关阅读:
    尾递归
    博客搬家 --- CSDN
    sublime text 插件集锦
    chrome 常用插件集锦
    IntelliJ Idea 2017 免费激活方法
    Mac下Java JNI 调C
    webgl学习笔记五-纹理
    webgl学习笔记四-动画
    webgl学习笔记三-平移旋转缩放
    webgl学习笔记二-绘图多点
  • 原文地址:https://www.cnblogs.com/xiaoduc-org/p/5411881.html
Copyright © 2011-2022 走看看