Java 二阶段 文件上传与下载

文件上传与下载

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1.上传文件

@WebServlet(name = "UploadingServlet", value = "/uploading")
@MultipartConfig()
public class UploadingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取绝对路径名
        String realPath = request.getServletContext().getRealPath("/upload");
        File dir = new File(realPath);
        //创建upload文件夹
        if (!dir.exists()) {
            dir.mkdirs();
        }
        //获取数据
        Collection<Part> parts = request.getParts();
        //判断表单元素是普通字段,还是文件
        for (Part part : parts) {
            String submittedFileName = part.getSubmittedFileName();
            if (submittedFileName == null) {
                String name = part.getName();
                String value = request.getParameter(name);
                System.out.println(name+"--"+value);
            }else {
            System.out.println(submittedFileName);
                part.write(realPath + File.separator + submittedFileName);
                //删除part
                part.delete();
                out.write(submittedFileName+"上传成功...");
            }
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

但是根据表单元素的名字来创建文件,不同的浏览器会有不同的表示。
IE浏览器:
在这里插入图片描述
所以

@WebServlet(name = "UploadingServlet", value = "/uploading")
@MultipartConfig()
public class UploadingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取绝对路径名
        String realPath = request.getServletContext().getRealPath("/upload");
        File dir = new File(realPath);
        //创建upload文件夹
        if (!dir.exists()) {
            dir.mkdirs();
        }
        //获取数据
        Collection<Part> parts = request.getParts();
        //判断表单元素是普通字段,还是文件
        for (Part part : parts) {
            String submittedFileName = part.getSubmittedFileName();
            if (submittedFileName == null) {
                String name = part.getName();
                String value = request.getParameter(name);
                System.out.println(name+"--"+value);
            }else {
		//从请求头中获取文件
                String header = part.getHeader("content-disposition");
                //截取
                String filename = header.substring(header.lastIndexOf("filename=") + 10, header.length() - 1);
                filename = filename.substring(filename.lastIndexOf("\\")+1);
                System.out.println(filename);

                part.write(realPath + File.separator + filename);
                //删除part
                part.delete();
                out.write(filename+"上传成功...");
            }
        }
    }

如果是不同的用户上传了相同的文件会覆盖,所以应该创建不同名称的文件。定义一个工具类,来生成不同的文件名

//创建新的文件名
public static String makeNewFileName(String filename) {
    //UUID 统一唯一标识码,认32位的16进制,比如:2d990e71-f5cf-476e-9e31-0dc7ad681638,把“-”去掉,就是一个32位的字符串
    String uuid = UUID.randomUUID().toString().replace("-", "");
    return uuid = uuid+"_"+filename;
}
@WebServlet(name = "UploadingServlet", value = "/uploading")
@MultipartConfig()
public class UploadingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取绝对路径名
        String realPath = request.getServletContext().getRealPath("/upload");
        File dir = new File(realPath);
        //创建upload文件夹
        if (!dir.exists()) {
            dir.mkdirs();
        }
        //获取数据
        Collection<Part> parts = request.getParts();
        //判断表单元素是普通字段,还是文件
        for (Part part : parts) {
            String submittedFileName = part.getSubmittedFileName();
            if (submittedFileName == null) {
                String name = part.getName();
                String value = request.getParameter(name);
                System.out.println(name+"--"+value);
            }else {
                //从请求头中获取文件
                String header = part.getHeader("content-disposition");
                //截取
                String filename = header.substring(header.lastIndexOf("filename=") + 10, header.length() - 1);
                filename = filename.substring(filename.lastIndexOf("\\")+1);
                //生成新的文件名
                String newFileName = UploadUtils.makeNewFileName(filename);
                System.out.println(newFileName);

                part.write(realPath + File.separator + newFileName);
                //删除part
                part.delete();
                out.write(filename+"上传成功...");
            }
        }
    }

还有问题,如果都往upload一个文件夹里存放文件,读1M的文件,和读1000个1k的文件,肯定是读1M的文件快,所以我们要让他们存放在不同的文件夹中,可以根据上传时间来设置文件夹。我则采用了另一种方式,通过新的文件名创建新的文件夹。我创建了一个生成新的路径的方法。

//生成新的路径,path是upload的路径。filename是新的文件名。
public static String makeNewPath(String path, String filename) {
    int num = filename.hashCode();
    int path1 = num&0xf;
    int path2 = (num>>4)&0xf;
    String newPath = path + File.separator +path1 +File.separator +path2;
    File dir = new File(newPath);
    if(!dir.exists()) {
        dir.mkdirs();
    }
    return newPath;
}
@WebServlet(name = "UploadingServlet", value = "/uploading")
@MultipartConfig()
public class UploadingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取绝对路径名
        String realPath = request.getServletContext().getRealPath("/upload");
        File dir = new File(realPath);
        //创建upload文件夹
        if (!dir.exists()) {
            dir.mkdirs();
        }
        //获取数据
        Collection<Part> parts = request.getParts();
        //判断表单元素是普通字段,还是文件
        for (Part part : parts) {
            String submittedFileName = part.getSubmittedFileName();
            if (submittedFileName == null) {
                String name = part.getName();
                String value = request.getParameter(name);
                System.out.println(name+"--"+value);
            }else {
                //从请求头中获取文件
                String header = part.getHeader("content-disposition");
                //截取
                String filename = header.substring(header.lastIndexOf("filename=") + 10, header.length() - 1);
                filename = filename.substring(filename.lastIndexOf("\\")+1);
                //生成新的文件名
                String newFileName = UploadUtils.makeNewFileName(filename);
                System.out.println(newFileName);
                //生成新的文件路径
                String newFilePath = UploadUtils.makeNewPath(realPath, newFileName);

                part.write(newFilePath + File.separator + newFileName);
                //删除part
                part.delete();
                out.write(filename+"上传成功...");
            }
        }
    }

我们还没有判断如果上传的文件为空,应该跳过,我们还可以限制上传文件的格式。

@WebServlet(name = "UploadingServlet", value = "/uploading")
@MultipartConfig()
public class UploadingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //添加接受的文件的格式
        List<String> allowExts = new ArrayList<>();
        allowExts.add("png");
        allowExts.add("jpg");
        allowExts.add("jpeg");
        //获取绝对路径名
        String realPath = request.getServletContext().getRealPath("/upload");
        File dir = new File(realPath);
        //创建upload文件夹
        if (!dir.exists()) {
            dir.mkdirs();
        }
        //获取数据
        Collection<Part> parts = request.getParts();
        //判断表单元素是普通字段,还是文件
        for (Part part : parts) {
            String submittedFileName = part.getSubmittedFileName();
            if (submittedFileName == null) {
                String name = part.getName();
                String value = request.getParameter(name);
                System.out.println(name+"--"+value);
            }else {
                //文件是空的
                if(submittedFileName.equals("")){
                    response.getWriter().write("文件不能为空...");
                    continue;
                }
                //从请求头中获取文件
                String header = part.getHeader("content-disposition");
                //截取
                String filename = header.substring(header.lastIndexOf("filename=") + 10, header.length() - 1);
                filename = filename.substring(filename.lastIndexOf("\\")+1);
                //判断是否符合接受的文件格式
                String ext = filename.substring(filename.lastIndexOf(".")+1);
                if(!allowExts.contains(ext)){
                    response.getWriter().write("文件格式不符合要求...");
                    continue;
                }
                //生成新的文件名
                String newFileName = UploadUtils.makeNewFileName(filename);
                System.out.println(newFileName);
                //生成新的文件路径
                String newFilePath = UploadUtils.makeNewPath(realPath, newFileName);

                part.write(newFilePath + File.separator + newFileName);
                //删除part
                part.delete();
                out.write(filename+"上传成功...");
            }
        }
    }

最后我们还要设置一下上传文件的大小。只需在注解中添加属性就可以

@MultipartConfig(maxFileSize = 1024*1024*5, maxRequestSize = 1024*1024*20)

单个文件不超过5M,全部上传文件不超过20M,如果超出了这个界限,会出现500错误页面。所以我们可以设计一个错误界面,去显示这个具体的错误。

还有个问题,我们存文件的地址是不安全的,可以通过路径能访问到,所以我们可以把文件放到WEB-INF文件夹中,这个是不能通过浏览器访问的,但可以通过Servlet来访问。所以说是安全的

最终版

@WebServlet(name = "UploadingServlet", value = "/uploading")
@MultipartConfig(maxFileSize = 1024*1024*5, maxRequestSize = 1024*1024*20)
public class UploadingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //添加接受的文件的格式
        List<String> allowExts = new ArrayList<>();
        allowExts.add("png");
        allowExts.add("jpg");
        allowExts.add("jpeg");
        //获取绝对路径名
        String realPath = request.getServletContext().getRealPath("/WEB-INF/upload");
        File dir = new File(realPath);
        //创建upload文件夹
        if (!dir.exists()) {
            dir.mkdirs();
        }
        //获取数据
        Collection<Part> parts = request.getParts();
        //判断表单元素是普通字段,还是文件
        for (Part part : parts) {
            String submittedFileName = part.getSubmittedFileName();
            if (submittedFileName == null) {
                String name = part.getName();
                String value = request.getParameter(name);
                System.out.println(name+"--"+value);
            }else {
                //文件是空的
                if(submittedFileName.equals("")){
                    response.getWriter().write("文件不能为空...");
                    continue;
                }
                //从请求头中获取文件
                String header = part.getHeader("content-disposition");
                //截取
                String filename = header.substring(header.lastIndexOf("filename=") + 10, header.length() - 1);
                filename = filename.substring(filename.lastIndexOf("\\")+1);
                //判断是否符合接受的文件格式
                String ext = filename.substring(filename.lastIndexOf(".")+1);
                if(!allowExts.contains(ext)){
                    response.getWriter().write("文件格式不符合要求...");
                    continue;
                }
                //生成新的文件名
                String newFileName = UploadUtils.makeNewFileName(filename);
                System.out.println(newFileName);
                //生成新的文件路径
                String newFilePath = UploadUtils.makeNewPath(realPath, newFileName);

                part.write(newFilePath + File.separator + newFileName);
                //删除part
                part.delete();
                out.write(filename+"上传成功...");
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值