Spring Web文件上传功能简述

toc

正文

在日常项目开发过程中,文件上传是一个非常常见的功能,当然正规项目都有专门的文件服务器保存上传的文件,实际只需要保存文件路径链接到数据库中即可,但在小型项目中可能没有专门的文件服务器用来存储这些文件,这时就需要我们自己手动实现文件上传功能了。

简单文件上传

在SpringWeb项目中要想实现文件上传也很简单,通过接收 MultipartFile类型的文件即可接收到文件参数,一个简单的文件上传Controller接口代码如下

java 复制代码
@RestController
@RequestMapping("/test")
public class TestController {
    @CrossOrigin
    @PostMapping("/file")
    public String testFileUpload(MultipartFile file){
        String oriName = file.getOriginalFilename();
        return "已收到上传文件:"+oriName;
    }
}

这时只需要前端通过<input type="file"/>标签获取文件并使用FormData的方式上传即可,简单代码如下

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FileUploadDoc</title>
    <style>
        .contain{
            margin-left: 300px;
            margin-top: 100px;
            border: blanchedalmond solid;
            width: 310px;
            padding: 10px;
        }
    </style>
</head>
<body>
<div class="contain">
    <input id="uploadedInput" type="file" name="uploadedFile">
    <button id="submitBtn">提交</button>
</div>
</body>
<script>
    let btn = document.getElementById("submitBtn")
    let fileInput = document.getElementById("uploadedInput")
    btn.addEventListener("click",()=>{
        let fileData=fileInput.files[0]
        let formData = new FormData()
        formData.append("file",fileData)
        //注意:这里不需要设置Content-Type参数
        let xhr = new XMLHttpRequest();
        xhr.open("POST","http://localhost:18080/test/file")
        xhr.send(formData)
        xhr.onreadystatechange=()=>{
            if (xhr.status===200){
                console.log(xhr.responseText)
            }
        }
    })
</script>
</html>

效果如下

选择文件后,通过点击提交按钮即可将所选文件上传到后端服务器。

这里有一个问题需要注意,如果上传失败报错,需要设置

  1. 最大文件大小,参数名spring.servlet.multipart.max-file-size,默认值1MB

  2. 单个请求最大值 ,参数名spring.servlet.multipart.max-request-size,默认值10MB

这两个参数,在SpringBoot项目中由于存在默认配置,可以不设置,若需要修改默认值则需根据实际情况设置这两个参数。

如果超出尺寸大小的限制会抛出这两个异常

  1. 文件大小超出限制异常为 FileSizeLimitExceededException
  2. 请求内容超出限制异常为 SizeLimitExceededException

文件写入

一般情况下的上传业务,需要将文件写入到固定的文件夹下,而当遇到同名文件时需要覆盖原来的文件。面对这种业务逻辑需要修改代码如下

java 复制代码
@CrossOrigin
@PostMapping("/file")
public String testFileUpload(MultipartFile file) throws IOException {
    if (file == null) {
        return "上传文件不能为空";
    }

    //获取文件名
    String oriName = file.getOriginalFilename();
    //文件保存文件夹
    String dirPath = "D:\\Activities\\temp_files";
    File serverFile = new File(dirPath, oriName);
    //判断文件是否存在
    if (serverFile.exists()) {
        serverFile.delete();
    } else {
        serverFile.createNewFile();
    }
    //读取文件并上传
    try (InputStream input = file.getInputStream();
         BufferedInputStream bIn = new BufferedInputStream(input);
         OutputStream output = new FileOutputStream(serverFile);
         BufferedOutputStream bOut = new BufferedOutputStream(output)) {
        byte[] byteArr = new byte[1024];
        int len = 0;
        while ((len = bIn.read(byteArr)) > 0) {
            bOut.write(byteArr, 0, len);
        }
    }

    return "已收到上传文件:" + oriName;
}

另一种常见的业务逻辑是,校验文件格式(如:只支持txt文件格式)后,对其进行重命名后返回一个网络地址,这时可使用以下代码

java 复制代码
@CrossOrigin
@PostMapping("/file")
public String testFileUpload(MultipartFile file) throws IOException {
    if (file == null) {
        return "上传文件不能为空";
    }

    StringBuffer fileNameBuf = new StringBuffer();
    fileNameBuf.append(System.currentTimeMillis()).append(UUID.randomUUID());
    String oriName = file.getOriginalFilename();
    //校验.txt和.TXT文件格式
    Pattern pattern = Pattern.compile("^.+[.txt|.TXT]$");
    if(pattern.matcher(oriName).matches()) {
        fileNameBuf.append(".txt");
    }else{
        return "文件格式错误,只支持txt文件";
    }

    String dirPath = "D:\\Activities\\temp_files";
    File serverFile = new File(dirPath, fileNameBuf.toString());
    if (serverFile.exists()) {
        return "文件上传失败,请重试";
    } else {
        serverFile.createNewFile();
    }
    try (InputStream input = file.getInputStream();
         BufferedInputStream bIn = new BufferedInputStream(input);
         OutputStream output = new FileOutputStream(serverFile);
         BufferedOutputStream bOut = new BufferedOutputStream(output)) {
        byte[] byteArr = new byte[1024];
        int len = 0;
        while ((len = bIn.read(byteArr)) > 0) {
            bOut.write(byteArr, 0, len);
        }
    }

    //生成网络链接
    StringBuffer webPath = new StringBuffer("文件上传成功,文件访问链接为:");
    webPath.append("https://img.sunyog.top/temp_files/").append(fileNameBuf);
    return webPath.toString();
}

总结

本文简单介绍了在Spring Web项目中文件上传相关的业务,在Spring中文件上传通过接收 MultipartFile类型的参数即可实现,获取到文件后可根据具体的业务逻辑进行相应处理。而在JavaScript中需要做的仅仅是获取所选文件,并通过FormData传输数据即可。


📩 联系方式

掘金: 我的掘金

CSDN: 我的CSDN

❗版权声明

本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问我的个人中心

相关推荐
刘一说几秒前
Pinia状态持久化的“隐形陷阱“:为什么页面刷新后状态丢失?
前端·javascript·vue.js
心柠6 分钟前
webpack
前端·webpack·node.js
C澒7 分钟前
前端编码规范
前端·团队开发·代码规范
Zhu_S W19 分钟前
基于Java和Redis实现排行榜功能
前端·bootstrap·html
小马_xiaoen38 分钟前
Vue3 + TS 实现长按指令 v-longPress:优雅解决移动端/PC端长按交互需求
前端·javascript·vue.js·typescript
147API1 小时前
改名后的24小时:npm 包抢注如何劫持开源项目供应链
前端·npm·node.js
ziqi5221 小时前
第二十二天笔记
前端·chrome·笔记
鹤归时起雾.1 小时前
react一阶段学习
前端·学习·react.js
2301_780669861 小时前
HTML-CSS-常见标签和样式(标题的排版、标题的样式、选择器、正文的排版、正文的样式、整体布局、盒子模型)
前端·css·html·javaweb
mseaspring1 小时前
一款高颜值SSH终端工具!基于Electron+Vue3开发,开源免费还好用
运维·前端·javascript·electron·ssh