javaWeb上传文件(二)——使用commons-fileupload

我们做上传头像功能,图片很小,可以使用第一篇中的方法,甚至可以直接使用Base64,以字符串的形式来上传。不过对一些更大的功能,如发帖,发说说等,要求图片比较大,也要求同时上传多张。对于上传一些大的文件,现在都是用的Apache的框架commons-fileupload,不得不说Apache真的是一个伟大的组织,几乎所有的框架,典型的如SpringMvc上传文件,也是使用的commons-fileupload。那么这里我们来看看如何直接使用commons-fileupload来上传文件吧。

一、学习要点
  1. 如何使用commons-fileupload
  2. 如何实现多个文件上传
  3. 如何限定文件的格式与数量
  4. 封装成一个工具类
二、commons-fileupload的使用

commons-fileupload的使用其实很简单:
①导入jar包

需要commons-io和commons-fileupload两个jar包,官网下载较慢,读者也可以自行去其他网站下载。

官网下载地址:http://commons.apache.org/proper/commons-fileupload/

②得到硬盘工厂

 DiskFileItemFactory factory = new DiskFileItemFactory();

③创建上传类

  ServletFileUpload upload = new ServletFileUpload(factory);

④获取上传的Item(需要传入HttpServletRequest对象)

   List<FileItem> itemList = upload.parseRequest(request);

⑤遍历Item列表


    for (FileItem item : itemList) {
            if (item.isFormField()) {//是表单属性

                //获取表单传进来的参数

            } else {//是文件

                //保存上传的文件
            }
        }

对于表单参数具体操作:

//获取表单名
String name=item.getFieldName();
//获取表单值
String content=item.getString("utf-8");

对于文件的具体操作:

//获取文件名
String fileName = item.getName();
//创建存放位置
String saveName = CommUtils.getUuidCode() + dotExtendName;
//保存文件(以流的形式写到服务器上)
File saveFile = new File(savePath + saveName);
FileOutputStream out = new FileOutputStream(saveFile);
InputStream in = item.getInputStream();
int len;
while ((len = in.read()) != -1) {
    out.write(len);
}
out.flush();

的确,使用方法还是简单的一匹的,其中有有一些异常需要抛出一下,下面会给出完整代码。

三、如何上传多个文件

我们可以看到,上传实际是通过遍历一个列表,那么我们对列表的每个Item进行遍历,将是文件类型的Item都分别保存下来,就实现了多张上传。

不过这里有一个问题,需要解决:我们一般在记录用户的图片的时候,为了提高数据库查询效率,通常都是将图片存在文件服务器,而数据库只保存图片的名称,这时候上传文件重名了怎么办?两个不同的用户的头像名称一样了,怎么知道谁该用哪一张?

答案很简单:我们重新给每个文件制定名字,保证我们上传的图片都有一个独一无二的名称。

①使用当前毫秒数+随机数命名

这种方式也存在安全性,万一两个用户在同一毫秒请求,且随机数刚好巧合了(虽然几率很小,但是可能发生),不推荐。

②使用uuid算法

uuid算法可以保证同一台机器,得到不同的名称。推荐使用。

   public static String getUuidCode() {
        return UUID.randomUUID().toString().replace("-", "");
    }

名称问题搞定了,上传多张也就不成问题了

四、如何限定文件格式与数量

我们遍历了Item列表,就可以对其文件后缀名进行检查,不合格就抛出异常,便达到了限定格式的效果。同样,只要判断Item列表的size就可以限定数量了,不过值得注意的是,限定的是表单与文件的总数量。

五、封装成util,完整代码

我们从异常、dao、service、action等层次,以用户上传头像为例完整地描述一次文件上传过程。

①异常

public class MyFileUploadException extends RuntimeException {
    public MyFileUploadException(String message, Throwable cause) {
        super(message, cause);
    }

    public MyFileUploadException(String message) {
        super(message);
    }
}

②工具类

import com.photograph_u.exception.MyFileUploadException;
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 javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FileUploadUtil {
    public static void upload(HttpServletRequest request, String savePath, int fieldCount, int fileCount) {
        Map<String, Object> parameterMap = new HashMap<>();
        List<String> fileList = new ArrayList<>();
        FileOutputStream out = null;
        InputStream in = null;
        if (!ServletFileUpload.isMultipartContent(request)) {
            throw new MyFileUploadException("表单属性设置不正确");
        }
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(16 * 1024);//占用运行内存16K,多余的存内存
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setSizeMax(5 * 1024 * 1024);//总大小限制5M
        upload.setFileSizeMax(700 * 1024);//单张限制700K
        File dir = new File(savePath);
        if (!dir.exists()) {
            dir.mkdirs();//创建目录(允许多级)
        }
        List<FileItem> itemList;
        try {
            itemList = upload.parseRequest(request);//获取多重表单
        } catch (FileUploadException e) {
            throw new MyFileUploadException("文件上传异常", e);
        }
        //检查文件数量
        if (itemList.size() > (fieldCount + fileCount)) {
            throw new MyFileUploadException("文件数量过多");
        }
        //遍历表单
        for (FileItem item : itemList) {
            if (item.isFormField()) {//是表单属性
                try {
                    parameterMap.put(item.getFieldName(), item.getString("utf-8"));
                } catch (UnsupportedEncodingException e) {
                    throw new MyFileUploadException("多重表单编码异常", e);
                }
            } else {//是文件
                String fileName = item.getName();
                if (!"".equals(fileName)) {//选择了文件
                    //检查文件类型是否正确
                    String dotExtendName = fileName.substring(fileName.lastIndexOf("."));
                    boolean allow = false;
                    String[] allowType = {".jpg", ".png", ".bmp", ".gif"};
                    for (String type : allowType) {
                        if (type.equals(dotExtendName))
                            allow = true;
                    }
                    if (!allow) {
                        throw new MyFileUploadException("文件类型不支持");
                    }
                    //保存上传文件
                    String saveName = CommUtils.getUuidCode() + dotExtendName;
                    File saveFile = new File(savePath + saveName);
                    try {
                        out = new FileOutputStream(saveFile);
                        in = item.getInputStream();
                        int len;
                        while ((len = in.read()) != -1) {
                            out.write(len);
                        }
                        out.flush();
                        fileList.add(saveName);
                        parameterMap.put("files", fileList);
                    } catch (Exception e) {
                        throw new MyFileUploadException("文件上传异常", e.getCause());
                    } finally {
                        try {
                            if (out != null) {
                                out.close();
                            }
                            if (in != null) {
                                in.close();
                            }
                        } catch (IOException e) {
                            throw new MyFileUploadException("文件上传异常", e);
                        }
                    }

                }
            }
        }
        request.setAttribute("parameterMap", parameterMap);
    }
}

③dao层

    //修改头像
    public boolean updateHeadImage(int userId, String headImage) {
        String sql = "update user set head_image=? where id=? and is_deleted=0";
        int count = update(sql, new Object[]{headImage, userId});
        return count == 1;
    }

④service层

    //设置头像
    public boolean setHeadImage(int userId, String headImage) {
        UserDao userDao = new UserDao();
        return userDao.updateHeadImage(userId, headImage);
    }

④action层

    //设置头像
    public void setHeadImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        MyResponse<String> myResponse = new MyResponse<>();
        int userId = (int) request.getSession().getAttribute("user_id");
        FileUploadUtil.upload(request, FileUriConsts.HEAD_IMAGE_URI, 0, 1);
        Map parameterMap = (Map) request.getAttribute("parameterMap");
        List fileList = (List) parameterMap.get("files");
        UserService service = new UserService();
        if (service.setHeadImage(userId, (String) fileList.get(0))) {
            myResponse.setCode(0);
            myResponse.setMessage("头像设置成功");
        } else {
            myResponse.setCode(1);
            myResponse.setMessage("头像设置失败");
        }
        ResponseUtil.sendResponse(response, myResponse);
    }

⑤文件保存路径


public class FileUriConsts {
    /**
     * windows下的路径
     */
//    public static final String HEAD_IMAGE_URI = "D:/photograph_u/head_images/";

    /**
     *linux下的路径
     */
    public static final String HEAD_IMAGE_URI = "/var/lib/tomcat7/webapps/photograph_u/head_images/";
}

⑥Html写法

上传头像
<form action="user/setHeadImage" enctype="multipart/form-data" method="post">
    <input type="file" name="file">
    <input type="submit" value="上传">
</form>

猜你喜欢

转载自blog.csdn.net/qq_35890572/article/details/81079144