文件上传下载及自己封装jar包

本文介绍文件上传下载的实现方法,包括使用特定格式的表单、第三方jar包处理、解决中文文件名乱码问题,以及如何封装成工具类和jar包方便复用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件上传下载及jar包封装

表单要求

对于表单上传,要求使用post请求方式,并且 enctype必须是如下类型

method="post" enctype="multipart/form-data" 
  • 1
  • 2
  • 3
  • 4

上传代码

当表单中的类型指定为multipart/form-data 时,无法通过getParameter获取请求参数,使用第三方jar包

commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar

response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");//
// 但它可以解决上传文件 的文件名为中文的乱码问题
String storagePath = getServletContext().getRealPath("/image");
// 判断当前文件夹是否存在,如果不存在,就创建一个新的
File file = new File(storagePath);
if (!file.exists()) {
    file.mkdirs();
}
// 判断表单是否是规定格式
boolean multipartContent = ServletFileUpload
            .isMultipartContent(request);
// 如果不是规定格式,提示表单问题
if (!multipartContent) {
    response.getWriter().write("表单有问题");
    return;
}
// 获取一个能够去表单文件的工厂
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 创建上传的对象
ServletFileUpload servletFileUpload = new ServletFileUpload(
            fileItemFactory);
try {
    //解析请求-获取表单中的字段集合
    List<FileItem> parseRequest = servletFileUpload
                .parseRequest(request);
        //遍历集合
        for (FileItem fileItem : parseRequest) {
            //判断是否是普通字段
            if (fileItem.isFormField()) {
                //获取字段名称
                String fieldName = fileItem.getFieldName();
                System.out.println(fieldName);
                //获取字段value
                String string = fileItem.getString("UTF-8");
                System.out.println(string);
            } else {
                // 说明是上传的文件
                String name = fileItem.getName();
                // 自己拼接路径
                String savePath = storagePath + "/"
                        + name.substring(name.lastIndexOf("/") + 1);
                // 开始读取文件,然后写入到存储的文件夹下
                FileOutputStream fileOutputStream = new FileOutputStream(
                        new File(savePath));
                //因为是文件,以流的形获取
                InputStream inputStream = fileItem.getInputStream();
                //使用工具类,读取表单中的文件,然后复制到输出流中去
                IOUtils.copy(inputStream, fileOutputStream);
                //关闭流
                fileOutputStream.close();
                inputStream.close();
            }
        }

    } catch (FileUploadException e) {
        e.printStackTrace();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

上传优化

  • 1.得到上传的文件要保存的位置,如果不想被随便访问,请放置到WEB-INF文件夹下边

    String storePath = getServletContext().getRealPath("/WEB-INF/images");
    
    • 1
    • 2
  • 2.判断文件上传的类型,如果对于要求上传图片的需求,添加图片的限制

    String mime = item.getContentType();//MIME类型    image/jpeg  image/bmp  
    if(mime.contains("image")){
    if("".equals(item.getName())){
            continue;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 3.文件名同名的问题,使用UUID生成一个唯一的随机名称

    fileName = UUID.randomUUID().toString()+"_"+fileName;
    
    • 1
    • 2
  • 4.分文件夹存储图片-按照日期方式存储图片

    public String createDirByDate(String path){
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    String dir = df.format(new Date());
    File file = new File(path +File.separator+dir);
    if(!file.exists()){
        file.mkdirs();
    }
    return dir;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 5.分文件夹存储图片二-按照Hash值存储图片

    public String createDirByHashCode(String path,String fileName){
    int hashcode = fileName.hashCode();//得到一个字符串的hashcode码   "
    int dir1 = hashcode&0xf;   //位与  得到一级子目录  (16个)
    int dir2 = (hashcode & 0xf0)>>4;// 得到的结果
    String childPath = dir1+File.separator+dir2;
    
    File file = new File(path,childPath);//第一个参数是父目录,第二个参数是子目录
    if(!file.exists()){
        file.mkdirs();
    }
    return childPath;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    }

    String savePath = storePath+File.separator+createDirByHashCode(storePath,fileName)+File.separator+fileName;
    
    • 1
    • 2

文件下载

  • 对于文件下载,主要分为两个步骤

  • 第一步:设置下载的响应头

    response.setHeader("Content-Dispostion", "attachment;fileName="
                + URLEncoder.encode(name, "UTF-8"));
    
    • 1
    • 2
    • 3
  • 第二步:读取文件流,通过响应的输出流打给客户端

    String name = realPath.substring(realPath.lastIndexOf("_"));
        response.setHeader("Content-Dispostion",    "attachment;fileName="
                + URLEncoder.encode(name, "UTF-8"));
        FileInputStream fileInputStream = new FileInputStream(new   File(
                realPath));
        ServletOutputStream outputStream =  response.getOutputStream();
        IOUtils.copy(fileInputStream, outputStream);
        fileInputStream.close();
        outputStream.close();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

自行封装文件上传的jar包

  • 对于像上传这样的常用功能,如果每次上传都写100 200行代码岂不是累屎,于是我们封装成工具类,来搞定这个事情

  • 定义一个静态的上传方法,要求提供三个参数,存储路径,请求参数,要封装成的对象T

  • 主要的代码和上传代码一致,不过,需要重点说的就是里边有一块反射的内容,对于T这个对象,要求在定义的时候就和表单中的字段名称一致,这样就可以做到通过反射属性名,来设置属性的值并不是多么高大上的东东…

    public static <T> void upload(String storagePath,
        HttpServletRequest httpServletRequest, T t) {
    
    boolean multipartContent = ServletFileUpload
            .isMultipartContent(httpServletRequest);
    
    // 上传文件的工厂
    FileItemFactory fileItemFactory = new DiskFileItemFactory();
    // 临时文件
    // 上传文件的对象
    ServletFileUpload servletFileUpload = new ServletFileUpload(
            fileItemFactory);
    // 解析请求
    try {
        List<FileItem> parseRequest = servletFileUpload
                .parseRequest(httpServletRequest);
    
        Class<? extends Object> tClazz = t.getClass();
        // 遍历传递的数据集合
        for (FileItem fileItem : parseRequest) {
            // 判断字段是什么类型
            boolean formField = fileItem.isFormField();
            // 普通类型
            if (formField) {
                // 获取字段名--name -password
    
                // username ---反射
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8");
    
                Field field = tClazz.getDeclaredField(name);
                if (field != null) {
                    // 暴力反射
                    field.setAccessible(true);
                    field.set(t, value);
                }
            } else {
                // 上传的文件类型
                // 文件的名称 c:/aa/ab.jpg
                // image/ab.jpg
                String name = fileItem.getName();
                String fileName = name.substring(name.lastIndexOf("/") + 1);
                fileName = UUID.randomUUID() + "_" + fileName;
                // 获取流的信息
                InputStream inputStream = fileItem.getInputStream();
                // 文件最终存储到的位置
                String targetPath = storagePath + "/"
                        + createDirByHashCode(storagePath, fileName) + "/"
                        + fileName;
                // 把流写到本地
                FileOutputStream fileOutputStream = new FileOutputStream(
                        new File(targetPath));
                // pic
                Field field = tClazz.getDeclaredField(fileItem
                        .getFieldName());
                if (field != null) {
                    // 暴力反射
                    field.setAccessible(true);
                    field.set(t, targetPath);
                }
                IOUtils.copy(inputStream, fileOutputStream);
                inputStream.close();
                fileOutputStream.close();
            }
        }
    
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
  • 顺便把下载的方法做一下简单封装,提供下载的路径,提供一个响应

    public static void downLoad(String path, HttpServletResponse resp) {
    
    try {
        FileInputStream fileInputStream = new FileInputStream(new File(path));
        // 输出流
        ServletOutputStream outputStream = resp.getOutputStream();
    
        IOUtils.copy(fileInputStream, outputStream);
    
        String name = path.substring(path.lastIndexOf("/") + 1);
    
        // 通知浏览器下载 文件名称
        resp.setHeader("Content-Dispostion", "attachment;fileName="
                + URLEncoder.encode(name, "UTF-8"));
        // 关流
        fileInputStream.close();
        outputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 如果你感觉搞成工具类还不过瘾,不妨给它做成jar包,也很简单,只需要在MyEclipse或者Eclipse中 export-java-jar 就可以啦,这样你的东西就可以很简单的让别人使用啦…

jar包如何使用?

  • 第一步:根据表单封装Bean

    比如表单中有字段 name password pic

    那封装成的Bean就包含 name password pic这几个属性

    private String name;
    private String password;
    private String pic;
    
    • 1
    • 2
    • 3
    • 4
  • 第二步:使用jar包方法

    //准备存储路径
    String storagePath = getServletContext().getRealPath("WEB-INF/image");
    //定义空对象
    User user = new User();
    //调用工具类方法
    LoadUtils.upload(storagePath, req, user);
    //数据就封装好了
    System.out.println(user.toString());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值