首页>代码>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日
最近浏览更多
sunlzh888888  LV28 2023年12月28日
asddwh  LV12 2023年12月26日
uni-code_0123  LV1 2023年11月29日
hongdongdong  LV12 2023年11月18日
19050126312  LV1 2023年10月19日
luandjustin 2023年7月3日
暂无贡献等级
asadda  LV2 2023年6月27日
A-sunny-day  LV4 2023年6月10日
aaaaaaa陈  LV1 2023年3月21日
一位靓仔路过  LV5 2022年11月4日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友