首页>代码>java servlet实现文件的上传功能>/upload/src/com/dreambamboo/controller/UploadServletDetails.java
package com.dream.bamboo;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

/**
 * @ClassName:UploadServletDetails
 * @Description:文件上传
 * @author :dreambamboo
 * @date:2018-12-04
 */
public class UploadServletDetails extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取上传文件的保存目录,将上传的文件保存在web目录下(但一般为了安全放在web-inf目录下,不允许外界直接访问,保证上传安全)
        String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
        //上传文件生产的临时文件保存目录
        String tmpPath = this.getServletContext().getRealPath("/WEB-INF/temp");

        File tmpFile = new File(tmpPath);
        //判断上传文件的保存目录是否存在
        if (!tmpFile.exists() && !tmpFile.isDirectory()){
            //如果目录不存在或者不是一个目录则需要创建目录
            tmpFile.mkdir();
        }
        //提示信息
        String message = "";
        //创建DiskFileItemFactory工厂
        DiskFileItemFactory dif = new DiskFileItemFactory();
        //设置工厂的缓冲区的大侠,当上传文件大小超过缓冲区的大小时,就会生成一个临时文件放到指定的临时目录中
        dif.setSizeThreshold(1024*1000);
        //设置上传时生成的临时文件的保存目录
        dif.setRepository(tmpFile);
        //创建文件上传解析器
        ServletFileUpload upload = new ServletFileUpload(dif);
        //监听文件上传进度
        upload.setProgressListener(new ProgressListener() {
            @Override
            public void update(long pBytesRead, long pContentLength, int i) {
                System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
            }
        });
        //解决上传文件名的中文乱码
        upload.setHeaderEncoding("UTF-8");
        //判断提交上来的数据是否是上传表单的数据
        if (!ServletFileUpload.isMultipartContent(req)){
            //按照传统方式获取数据
            return;
        }
        //设置上传单个文件的最大值,目前设置的是1024*1024*2 = 2M
        upload.setFileSizeMax(2*1024*1024);
        //设置上传文件的总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10M
        upload.setSizeMax(10*1024*1024);
        //使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
        try {
            List<FileItem> list = upload.parseRequest(req);
            //如果fileitem中封装的是普通输入项数据
            for (FileItem item:list) {
                if (item.isFormField()){
                    String name = item.getFieldName();
                    //解决普通输入项的数据的中文乱码问题
                    String value = item.getString("UTF-8");

                }else{
                    //如果fileitem中封装的是上传数据
                    //得到上传文件的名称
                    String filename = item.getName();
                    if (filename == null || filename.trim().equals("")){
                        continue;
                    }
                    //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
                    //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                    if ((filename.lastIndexOf("\\")) != -1){
                        filename = filename.substring(filename.lastIndexOf("\\") + 1);
                    }
                    //得到上传文件的扩展名,用于对上传文件的类型进行判断和限制
                    String fileExtName = filename.substring(filename.lastIndexOf(".") + 1);
                    //获取item中的上传文件的输入流
                    InputStream inputStream = item.getInputStream();
                    //得到文件保存的名称
                    String saveFileName = makeFileName(filename);
                    //得到文件的保存目录
                    String realSavePath = makeFilePath(saveFileName,savePath);
                    //创建文件输出流
                    FileOutputStream fileOutputStream = new FileOutputStream(realSavePath + "\\" + saveFileName);
                    //创建一个缓冲区
                    byte buffer[] = new byte[1024];
                    //判断输入流中的数据是否已经读完的标识
                    int len = 0;
                    //循环将输入流中的数据督导缓冲区中,(len = inputStream.read(buffer))>0就表示inputstream里面还有数据
                    while ((len = inputStream.read(buffer)) > 0){
                        //使用FileOutputStream输出流将缓冲区中的数据写入到指定的文件目录(savePath + "\\" + filename) 中
                        fileOutputStream.write(buffer,0,len);
                    }
                    //关闭输出流
                    fileOutputStream.close();
                    //关闭输入流
                    inputStream.close();
                    //删除处理文件上传时产生的临时文件
                    //item.delete();
                    message = "文件上传成功";
                }

            }
        } catch (FileUploadBase.FileSizeLimitExceededException e){
            e.printStackTrace();
            req.setAttribute("message","单个文件超出最大值!!!");
            req.getRequestDispatcher("/result.jsp").forward(req,resp);
            return;
        } catch (FileUploadBase.SizeLimitExceededException e){
            e.printStackTrace();
            req.setAttribute("message","上传文件的总的大小超出最大值!!!");
            req.getRequestDispatcher("/result.jsp").forward(req,resp);
            return;
        } catch (Exception e){
            message = "文件上传失败";
            e.printStackTrace();
        }
        req.setAttribute("message",message);
        req.getRequestDispatcher("/result.jsp").forward(req,resp);
    }

    /**
     * 为防止一个目录下面出现太多的文件,要使用hash算法打散存储
     * @Method:makeFilePath
     * @param saveFileName  文件名,要根据文件名生成存储路径
     * @param savePath  文件存储路径
     * @return  新的存储目录
     */
    private String makeFilePath(String saveFileName, String savePath) {
        //得到文件名的hashCode值,得到的就是filename这个字符串对象在内存中的地址
        int hashcode = saveFileName.hashCode();
        int dir1 = hashcode & 0xf;//0--15
        int dir2 = (hashcode & 0xf0)>>4;//0--16
        //构造新的保存目录
        String dir = savePath + "\\" + dir1 + "\\" + dir2;
        //File既可以代表文件又可以代表目录
        File file = new File(dir);
        //判断目录是否存在
        if (!file.exists()){
            //如果目录不存在则穿件新的目录
            file.mkdirs();
        }
        return dir;
    }

    /**
     * @Method:makeFileName
     * @Description:生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
     * @param filename  文件的原始名称
     * @return uuid+"_"+文件的原始名称
     */
    private String makeFileName(String filename) {
        //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
        return UUID.randomUUID().toString() + "_" + filename;
    }
}
最近下载更多
19050126312  LV1 2023年10月19日
sanchez1  LV1 2021年10月12日
newplayer  LV1 2021年5月22日
17587079094  LV6 2020年11月16日
java_php  LV11 2020年10月17日
563066115  LV2 2020年5月7日
user12580  LV5 2020年3月20日
wuwu55  LV1 2019年10月21日
wq66618  LV1 2019年9月3日
zdm568  LV3 2019年8月23日
最近浏览更多
新哥新奇士橙  LV4 1月26日
214329 2024年11月29日
暂无贡献等级
sunlzh888888  LV29 2023年12月28日
asddwh  LV13 2023年12月26日
uni-code_0123  LV1 2023年11月29日
hongdongdong  LV14 2023年11月18日
19050126312  LV1 2023年10月19日
luandjustin 2023年7月3日
暂无贡献等级
asadda  LV2 2023年6月27日
A-sunny-day  LV4 2023年6月10日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友