[FE] 用 FormData 上传多个文件到 MultipartFile[] 接口

[FE] 用 FormData 上传多个文件到 MultipartFile[] 接口,第1张

最近有一个场景,在提交春乱表单的时候,需要实现添加附件的功能,

表单内容要先提交到服务端,创建一个 issue,然后再将附件添加到这个 issue 中。

所以,附件在用户添加的时候,是 没有立即上传 的,

用户可以随意在浏览器端添加和删除,issue 创建后再一起上传

前端采用的组件库是 antd ,用到了 upload 组件。

服务端接口是自定义实现的,也许并不支持 antd upload 上传组件的规范。

服务端接受数据时,使用了 MultipartFile ,这是 Spring 框架中常用的 写法 。

我们先看看 html input[type=file] 组件默认行为,

点击 “选择文件”,浏览器会d出一个窗口,

选中一个文件,点 “打开”,就会触发 onchange 事件,

在 onchange 事件蔽森磨中,可以通过 e.target.files[0] 拿到刚才上传的那个 File 对象

再来看一下 upload 组件的默认行为,

点击 “添加”,浏览器也会d出那个选择文件的窗口,

选中一个文件,点 “打开”,发现上传失败了。

打开控制台,看到 upload 组件向 / 这个地址发送了一个 POST 请求,

数据格式如下,

我们可以向 upload 组件传入 action 参数,修改 POST 请求地址,

但是,选中文件后立即上传 不符合 我们的场景,我们需要提交表单之后,将多个文件统一上传。

所以我们得自定义 upload 组件的宏斗行为。

upload 组件的有一个 customRequest 属性( #api ),

它可以配置自定义的上传行为。

我们的思路是,先将选中后自动上传的行为取消掉,然后再在提交表单后统一上传。

取消自动上传 的实现片段如下,

我们只需要在 customRequest 回调中,调用它的 onSuccess 参数即可。

删除也是可以用的,

现在我们添加两个附件,

接着来看前端怎样将这些附件,统一上传给服务端,具体实现如下,

可以看到请求成功了(项目中的 url 跟本例稍有不同,下图只为了示意),

还有几个需要注意的点:

上文 httpClient.post 实际调用了 XMLHttpRequest 发送请求,可能会遇到 跨域 的问题。

所以在调试上传接口的时候,需要检查一下服务端的配置,是否支持跨域请求。

CORS 相关的内容大致如下:

在预检请求阶段,服务端对 OPTIONS 请求的响应头中会包含 Access-Control-Allow-Origin ,

表明服务端接受该域 http://foo.example 的跨域请求。

注:

这里需要后端实现 OPTIONS 方法,后端框架一般会通过配置方式统一处理(返回 200 或 204,不能是 4xx)。

如果未配置统一处理方式,框架可能会直接返回 404 导致预检请求失败,CORS 请求也会失败。

使用 XMLHttpRequest 发送请求时,也可以携带 cookie 信息,

同时 预检请求中服务端响应头,也要包含 Access-Control-Allow-Credentials ,否则就不会发送 cookie

对于附带 cookie 的请求,服务器不能设置 Access-Control-Allow-Origin 的值为 “ * ”,否则请求将会失败。

而将 Access-Control-Allow-Origin 的值设置为具体的地址 http://foo.example ,请求才能成功。

我们上传功能用到了携带 cookie 的跨域请求,

可以看到服务端响应头中确实包含了, Access-Control-Allow-Credentials 和 Access-Control-Allow-Origin 两个字段。

Spring: Uploading Files

Spring: org.springframework.web.multipart #MultipartFile

ant-design v4.11.1

Ant Design - Upload #API

MDN: CORS

MultipartFile提供了以下方锋饥法来获取上传文件的信息:

getOriginalFilename,获取上传的文件名字;

getBytes,获取上传文件内容,转为字节数组;

getInputStream,获取一个InputStream;

isEmpty,文件上传内容为空,或者根本就没有文件上传;

getSize,文件上传的大小。

transferTo(File dest),保存文件到目标文件系统;

同时上传多个文件,则使用MultipartFile数组类来接受多个文件上传:

//多文件上传@RequestMapping(value = "/batch/upload", method = RequestMethod.POST)

    @ResponseBody    public String handleFileUpload(HttpServletRequest request){

        List<MultipartFile>files = ((MultipartHttpServletRequest) request)

                .getFiles("file")

        MultipartFile file = null

        BufferedOutputStream stream = null

        for (int i = 0i <files.size()++i) {

            file = files.get(i)

            if (!file.isEmpty()) {

                try {

           槐基陆         byte[] bytes = file.getBytes()

                    stream = new BufferedOutputStream(new FileOutputStream(

                            new File(file.getOriginalFilename())))

                    stream.write(bytes)

                    stream.close()

                } catch (Exception e) {

                    stream = null

                    return "You failed to upload " + i + " =>"                 铅顷           + e.getMessage()

                }

            } else {

                return "You failed to upload " + i

                        + " because the file was empty."

            }

        }

        return "upload successful"

    }

可以通过配置application.properties对SpringBoot上传的文件进行限定默认为如下配置:

spring.servlet.multipart.enabled=true

spring.servlet.multipart.file-size-threshold=0

spring.servlet.multipart.location=

spring.servlet.multipart.max-file-size=1MB

spring.servlet.multipart.max-request-size=10MB

spring.servlet.multipart.resolve-lazily=false

enabled默认为true,既允许附件上传。

file-size-threshold限定了当上传文件超过一定长度时,就先写到临时文件里。有助于上传文件不占用过多的内存,单位是MB或KB,默认0,既不限定阈值。

location指的是临时文件的存放目录,如果不设定,则web服务器提供一个临时目录。

max-file-size属性指定了单个文件的最大长度,默认1MB,max-request-size属性说明单次HTTP请求上传的最大长度,默认10MB.

resolve-lazily表示当文件和参数被访问的时候再被解析成文件。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/tougao/12129487.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存