spring-boot 实现多文件上传功能

前言

最近我在B站的学相思学习了飞哥的spring-boot实现的文件上传功能,我又在原有的基础上加了一点新的功能,不再是单文件上传,而是多文件上传功能,视频中飞哥也提供了思路,闲着没事也可以看看他的视频,懂得学习别人的知识同时多做分享,时刻怀揣感恩的心。
https://www.bilibili.com/video/BV1C3411b7wt?spm_id_from=333.999.0.0

本地文件上传的原理

本地文件上传的原理,类似于文件的拷贝,就是从一个文件夹中拷贝到另一个文件夹中。

代码块

  • 引入pom依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-freemarker</artifactId>
 </dependency>
  • 创建测试静态HTML页面
    upload.html
<body>
<h3>文件上传</h3>

<form action="/upload/file" enctype="multipart/form-data" method="post" id="image">
    <input name="dir" value="bus">
    <input type="file" name="file" multiple onchange="upload()">
</form>
<script>
     function upload  (){
         document.getElementById("image").submit();
    }
</script>
</body>
  • 后端映射页面
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/page")
public class PageController {

    @RequestMapping("/upload")
    public String upload(){
        return "upload";
    }
}
  • 全局配置

    application.yaml

 spring:
  profiles:
#    激活测试环境
    active: dev
  freemarker:
    suffix: .html
    cache: false
  servlet:
    multipart:
#      是否支持多部分上传。
      enabled: true
#      最大文件大小
      max-file-size: 20MB
#      请求文件总大小
      max-request-size: 100MB
#      文件写入磁盘的阈值。
      file-size-threshold: 20MB
#      临时文件存储目录
      location: G:/date/temp
server:
  port: 8080

application-dev.yaml

file:
#  服务器对外静态资源访问目录
  server-path: /uploads/**
#  本地服务静态资源储存目录
  local-path: G:/temp/
#  服务器访问路径
  static-path: http://localhost:8080
  • 创建文件上传服务接口
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Map;

public interface UploadService {

    Map<String, List<String>> upload(List<MultipartFile> multipartFile, String dir) throws IOException;
}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class UploadServiceImpl implements UploadService {

//    访问请求头
    @Value("${file.static-path}")
    public String staticPath;
//    本地储存地址
    @Value("${file.local-path}")
    public String localPath;

    /**
     * MultipartFile 这个对象是  SpringMVC提供的文件上传的可接受的类
     * 他的底层自动会和HttpServletRequest request中的request.getInputStream()融合
     * 从而达到文件上传的效果
     *
     * @author chenlirun
     * @date 2021/11/20 10:14
     */
    @Override
    public Map<String, List<String>> upload(List<MultipartFile> multipartFiles, String dir) {
        Map<String, List<String>> map = new HashMap<>();
        List<String> strings = new ArrayList<>();
        try {
            for (MultipartFile multipartFile : multipartFiles) {
//            获取本地上传文件的文件真实名称
                String realFileName = multipartFile.getOriginalFilename();
//            截取文件名的后缀
                String imgSuffix = realFileName.substring(realFileName.lastIndexOf("."));
//            生成唯一的文件名称
                String newFileName = UUID.randomUUID() + imgSuffix;

//            日期目录,做隔离,防止图片都放到一起,未来找的时候不好找
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                String datePath = dateFormat.format(new Date());
                File targetFile = new File(localPath + dir, datePath);
                if (!targetFile.exists()) targetFile.mkdirs();
//            指定文件上传以后的文件目录
                File fileName = new File(targetFile, newFileName);
//            指定文件上传的路径
                multipartFile.transferTo(fileName);
//                返回访问路径地址
                String accessName = staticPath + "/uploads" + "/" + dir + "/" + datePath + "/" + newFileName;
                strings.add(accessName);
            }
            map.put("image",strings);
            return map;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

  • 创建后端控制层
import com.example.demo.service.UploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.Map;

@Controller
public class UploadController {

    @Autowired
    UploadService uploadService;

    /**
     * @Param multipartFile 上传的文件
     * @Param HttpServletRequest request 获取请求头中 用户设定的路径信息
     * @author chenlirun
     * @date 2021/11/21 11:59
     */
    @ResponseBody
    @PostMapping("/upload/file")
    public Object upload(@RequestParam("file") List<MultipartFile> multipartFile, HttpServletRequest request) throws IOException {

        if (multipartFile.isEmpty())
            return "文件上传有误";
        String dir = request.getParameter("dir");
        Map<String, List<String>> upload = uploadService.upload(multipartFile, dir);
        return upload;
    }
}
  • 测试文件上传

上传文件功能触发后,我在后端打了一个dugger断点,可以看到我们上传文件时的信息。通过这些信息我们可以做很多事情

  • 配置临时文件的地址
  • 配置文件的大小
  • 配置文件的格式

我们看到文件上传不会直接上传到真实文件目录中,他一定会先创建一个临时文件,经过临时文件的中转后,才到真实目录。作用是:

  • 防止网络断开或者用户直接刷新或者是取消,因为这样会造成大量的垃圾文件的产生。
  • 保证真实目录的文件真实有效。

在这里插入图片描述

完成上述的所有步骤,可以完成多文件上传的功能,并返回给我们一个json格式的字符串。

{"image":["http://localhost:8080/uploads/bus/2021-11-21/a1a65455-312b-42bb-b899-764e02f8bfd4.jpg"]}

但是我们并不能通过返回的json字符串路径访问到文件。但不要急我们下面会讲到。


  • 配置静态资源访问目录
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Value("${file.server-path}")
    public String serverPath;

    @Value("${file.local-path}")
    public String localPath;

    /**
     * springboot中SpringMVC让开发者去配置文件上传的额外静态资源服务配置
     * @author chenlirun
     * @date 2021/11/20 15:34
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
       /**
         * addResourceHandler() :暴露对外访问静态页面的地址
         * addResourceLocations() : 本地存储静态资源的目录
         */
        registry.addResourceHandler(serverPath).addResourceLocations("file:"+localPath);
    }
}

完成这个配置就可以通过之前获得的地址访问了

http://localhost:8080/uploads/bus/2021-11-21/a1a65455-312b-42bb-b899-764e02f8bfd4.jpg
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平平常常一般牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值