当前位置: 首页 > article >正文

SpringBoot 整合 apache fileupload 轻松实现文件上传与下载(通用版)

我们以Thymeleaf页面模板引擎为例,简单介绍利用 apache fileupload 工具实现文件上传的功能。

2.1、添加相关依赖包

首先创建一个基础的 Spring Boot 项目,并引入相关的依赖包。

图片

2.2、添加相关配置参数

图片

图片

2.3、文件上传示例

图片

图片

对应文件上传的Controller类,示例如下:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

@Controller
public class ApacheFileController {

    /**
     * 定义文件上传的目录
     */
    private static String FILE_DIR = "/Users/demo/file";


    /**
     * 访问 upload3 路径时,跳转到apacheUpload.html页面
     * @return
     */
    @GetMapping("/upload3")
    public String index() {
        return "apacheUpload";
    }

    /**
     * 上传文件,支持多文件/表单上传
     * @param request
     * @throws Exception
     */
    @PostMapping("/apacheFileUpload")
    @ResponseBody
    public String fileUpload(HttpServletRequest request) throws Exception {
        // 判断上传的文件是普通的表单还是带文件的表单
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if(!isMultipart){
            // 终止方法运行,说明这是一个普通的表单,直接返回
            return "Upload file fail";
        }
        // 1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的
        DiskFileItemFactory factory = getDiskFileItemFactory();
        // 2.获取ServletFileUpload
        ServletFileUpload upload = getServletFileUpload(factory);
        // 3.处理上传的文件
        List<FileItem> fileItems = upload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
            // 判断上传的文件是普通的表单还是带文件的表单
            if (fileItem.isFormField()) {
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8"); // 处理乱码
                System.out.println(name + ": " + value);
            } else {
                // 处理文件
                String filePath = FILE_DIR + "/" + fileItem.getName();
                try(InputStream inputStream = fileItem.getInputStream();
                    OutputStream outputStream = new FileOutputStream(filePath)) {
                    // 拷贝文件流
                    IOUtils.copy(inputStream, outputStream);
                }
                // 清除临时文件
                fileItem.delete();
                System.out.println("上传成功,文件名:" + fileItem.getName());
            }
        }
        return "Upload file success";
    }


    /**
     * 创建DiskFileItemFactory对象
     * @return
     */
    private DiskFileItemFactory getDiskFileItemFactory() {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置一个缓冲区大小, 当文件大于这个缓冲区大小的时候, 就会放到临时磁盘目录,防止内存崩溃
        factory.setSizeThreshold(1024 * 1024);
        // 设置临时磁盘目录, 接收上传的 File
        factory.setRepository(new File(FILE_DIR + "/cache"));
        return factory;
    }

    /**
     * 获取ServletFileUpload
     * @param factory
     * @return
     */
    private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 监听上传进度
        upload.setProgressListener(new ProgressListener() {

            @Override
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("总大小:" + pContentLength + ",已上传:" + pBytesRead);
            }
        });
        // 处理乱码问题
        upload.setHeaderEncoding("UTF-8");
        // 设置单个文件的最大值,-1:表示无限制
        upload.setFileSizeMax(-1L);
        return upload;
    }
}

启动服务后,访问http://localhost:8080/upload3,可以看到如下界面:

图片

图片

图片

在服务控制台,还可以看到上传的进度信息。

图片

2.4、文件下载示例

图片

@Controller
public class DownloadController {

    private static final String SRC_PATH = "/Users/demo/file";

    /**
     * 通过文件名获取文件并以流的形式返回给客户端
     * @param filename
     * @param response
     */
    @GetMapping("/download/{filename:.+}")
    public void download(@PathVariable String filename, HttpServletResponse response) throws Exception {
        File file = new File(SRC_PATH +'/'+ filename);
        if(!file.exists()){
            throw new RuntimeException("下载文件不存在");
        }
        response.reset();
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("UTF-8");
        response.setContentLength((int) file.length());
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));

        // 使用缓存流,边读边写
        try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
            OutputStream os  = response.getOutputStream();
            byte[] buff = new byte[1024];
            int i;
            while ((i = bis.read(buff)) != -1) {
                os.write(buff, 0, i);
                os.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException("下载文件失败");
        }
    }
}

图片

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!


http://www.kler.cn/a/316830.html

相关文章:

  • 马斯克万卡集群AI数据中心引发的科技涟漪:智算数据中心挑战与机遇的全景洞察
  • 标准C++ 字符串
  • 虚幻引擎 CEO 谈元宇宙:发展、策略与布局
  • Microsoft 365 Exchange如何设置可信发件IP白名单
  • 【软件工程】一篇入门UML建模图(类图)
  • 如何从头开始构建神经网络?(附教程)
  • LeetCode 260. 只出现一次的数字 III
  • 用Python提取PowerPoint演示文稿中的音频和视频
  • CVE-2024-46101
  • 0.初始化项目(Vue2升级到Vue3)
  • 物联网新闻2024.09.16-2024.09.22
  • flume系列之:出现数据堆积时临时增大sink端消费能力
  • LAMP环境搭建记录:基于VM的Ubuntu虚拟机
  • 编译成功!QT/6.7.2/Creator编译Windows64 MySQL驱动(MSVC版)
  • (学习记录)使用 STM32CubeMX——GPIO引脚输入配置
  • 实时数据的处理一致性
  • JavaScript(JS)学习笔记 3(DOM简介 事件简介 元素修改 节点操作 事件操作)
  • MySQL:事务隔离级别
  • Kubernets基础-包管理工具Helm详解
  • 计算机组成原理==初识二进制运算
  • Redisson分布式锁主从一致性问题
  • CentOS修改主机名
  • 【已解决】如何使用JAVA 语言实现二分查找-二分搜索折半查找【算法】手把手学会二分查找【数据结构与算法】
  • 用Qt 对接‌百度AI平台
  • 响应式流规范
  • 胤娲科技:谷歌DeepMind祭出蛋白质设计新AI——癌症治疗迎来曙光