java web的文件上传

今天学习了javaWeb的文件上传功能。


首先要导入两个相关的jar包,一个是Apache的commons-fileupload包,一个Apache的commons-io包,在网上或者在Apache都能找到,并导到工程文件内。
这里写图片描述


jsp端通过form表单进行对服务器的提交:

 <!-- 以流的形式提交表单 -->
    <form action="${pageContext.request.contextPath}/servlet/Download" enctype="multipart/form-data" method="post">
        上传用户:<input type="text" name="name"><br/>
        上传文件1:<input type="file" name="file1"><br/>
        上传文件2:<input type="file" name="file2"><br/>
        <input type="submit" value="提交">
    </form>
enctype="multipart/form-data"       //以流的形式提交表单,支持任何文件上传

package com.lk;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
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.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class Download extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
        String savePath = this.getServletContext().getRealPath(
                "/WEB-INF/upload");
        File file = new File(savePath);
        // 判断上传文件的保存目录是否存在
        if (!file.exists() && !file.isDirectory()) {
            System.out.println(savePath + "目录不存在,需要创建");
            // 创建目录
            file.mkdirs();
        }

        try {
            // 创建一个DiskFileItemFactory工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setHeaderEncoding("UTF-8");

            // 查看是否以流的形式把表单传进
            if (!upload.isMultipartContent(request)) {
                // 不是就按正常的方式执行
                return;
            }
            // 使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
            List<FileItem> fileItems = upload.parseRequest(request);

            for (FileItem item : fileItems) {
                // 判断FileItem的数据类型
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    String value = item.getString("UTF-8");
                    System.out.println("name" + name + "   " + "value" + value);
                } else {
                    // 上传的为文件
                    String filename = item.getName();
                    filename = filename
                            .substring(filename.lastIndexOf("\\") + 1);

                    // 读取文件,io流操作
                    InputStream in = item.getInputStream();
                    File file2 = new File(savePath + "\\" + filename);
                    FileOutputStream out = new FileOutputStream(file2);
                    byte buf[] = new byte[1024];
                    int len = 0;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    in.close();
                    out.close();
                }

            }
        } catch (Exception e) {
            request.setAttribute("message", "上传失败");
            e.printStackTrace();
        }

    }

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

注意事项:
1.乱码问题,上传的文件名乱码,普通表单乱码问题(在上面的代码中已经解决)

//文件名乱码的解决方式
upload.setHeaderEncoding("UTF-8");
//普通表单乱码问题的解决方式
String value = item.getString("UTF-8");

2.上传的文件应该受到保护,外界无法直接访问
3.为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
4.为防止一个目录下面出现太多文件,要使用hash算法打散存储。
5.要限制上传文件的最大值。
6.要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
7.删除零时文件。在关闭流前用 item.delete;

package com.lk;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
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.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.taglibs.standard.tag.el.sql.UpdateTag;

public class Download extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
        String savePath = this.getServletContext().getRealPath(
                "/WEB-INF/upload");

        try {
            // 创建一个DiskFileItemFactory工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp")));
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setHeaderEncoding("UTF-8");

            // 查看是否以流的形式把表单传进
            if (!upload.isMultipartContent(request)) {
                return;
            }

            //限制单个文件的大小
            //upload.setFileSizeMax(1024);

            // 使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
            List<FileItem> fileItems = upload.parseRequest(request);

            for (FileItem item : fileItems) {
                // 判断FileItem的数据类型
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    String value = item.getString("UTF-8");
                    System.out.println("name" + name + "   " + "value" + value);
                } else {
                    // 得到上传的文件名称,不同电脑的名字不同判断下是否为空
                    String filename = item.getName();
                    if(filename==null||filename.equals("")){
                        continue;
                    }
                    filename = filename
                            .substring(filename.lastIndexOf("\\") + 1);
                    filename = getUnqieName(filename);
                    String dirName = getSavePath(savePath, filename);

                    // 读取文件
                    InputStream in = item.getInputStream();
                    File file2 = new File(dirName + "\\" + filename);

                    FileOutputStream out = new FileOutputStream(file2);

                    byte buf[] = new byte[1024];
                    int len = 0;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    item.delete();
                    in.close();
                    out.close();
                }

            }
        }catch(FileUploadBase.FileSizeLimitExceededException e){
            e.printStackTrace();
            request.setAttribute("message", "文件太大");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return ;
        }
        catch (Exception e) {
            request.setAttribute("message", "上传失败");
            e.printStackTrace();
        }
    }

    // 相同名的文件得到不同的名字
    public String getUnqieName(String fileName) {
        return UUID.randomUUID() + "_" + fileName;
    }

    // 产生多个文件夹保存,用hash打散储存
    public String getSavePath(String savePath, String fileName) {
        int fileHash = fileName.hashCode();
        // 分别通过位运算,得出12级目录的目录名
        int file1 = fileHash & 0Xf; // 取fileHash最后四位数字
        int file2 = fileHash & 0Xf0>>4; // 取fileHash最后四~八位数字
        String dir = savePath + "\\" + file1 + "\\" + file2;

        File file = new File(dir);
        // 创建文件
        if (!file.exists()) {
            file.mkdirs();
        }
        return dir;
    }

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

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值