一、场景描述
在互联网开发的过程中,往往需要实现文件上传的功能,我们可以借助比较好的第三方文件服务器:七牛云等等。但是也有一些需要直接通过 HTTP POST
文件到应用服务器进行特殊处理的功能实现。
通过以上的介绍,就应引申出了这篇文章,Spring Boot
使用 MultipartFile
接收来自表单的 file
文件,然后进行服务器上传是一个项目的基本需求。下面我们就代码加调试的方式来解读整个 HTTP POST
文件到服务器端的整个过程。
二、文件上传
-
前端我们采用
POST MAN
来实现文件上传的调试工作
-
服务器端接收文件的源码
-
Controller
@PostMapping("/Content") //@Async(value = ExecuteName.MEDIA) public DataResult mediaAudit(@RequestParam(value = "Thumbnail", required = false) MultipartFile thumbnail, @RequestParam("File") MultipartFile file, HttpServletRequest request, HttpServletResponse response) { response.setHeader("Content-Type", "application/json;charset=UTF-8"); response.setHeader("tid", UUID.randomUUID().toString()); response.setStatus(HttpServletResponse.SC_OK); Boolean result = mediaFrontService.mediaAudit(thumbnail, file, request); if (result) { return DataResult.success(); } return DataResult.getDataResult(MediaServerResponseCode.MEDIA_BUSY); }
-
Service
@Override public Boolean mediaAudit(MultipartFile thumbnail, MultipartFile file) { try { // 缩略图处理 if (!thumbnail.isEmpty()) { // 获取原始文件名称 String thumbnailFilename = thumbnail.getOriginalFilename(); // 保存文件 thumbnail.transferTo(new File("/Users/rambo/Desktop/Temp/" + thumbnailFilename)); } // 正文图处理 if (!file.isEmpty()) { // 获取原始文件名称 String filename = file.getOriginalFilename(); // 保存文件 file.transferTo(new File("/Users/rambo/Desktop/Temp/" + filename)); } else { throw new BusinessException(MediaServerResponseCode.MEDIA_PARAMS); } } catch (IOException e) { e.printStackTrace(); throw new BusinessException(MediaServerResponseCode.MEDIA_BUSY.getCode(), e.getMessage()); } return true; }
-
三、过程解读
-
前端请求报文
-
抓包图
-
请求行
# 请求方式 + 请求URL + 请求协议 POST /Content HTTP/1.1
-
请求头
# Content-Type 指明数据以 multipart/form-data 来编码 # 生成一个 boundary 用于分割不同的字段,为避免与正文内容重复,boundary 内容很长很复杂 Content-Type multipart/form-data; boundary=--------------------------988921756836113674975210
-
请求体
传输的是文件,包含文件名和文件类型信息,消息体以
--boundary
标示开始,最后以--boundary--
标示结束----------------------------988921756836113674975210 Content-Disposition: form-data; name="Thumbnail"; filename="thumb.jpg" Content-Type: image/jpeg ÿØÿà™ÿÙ... ... ... ... ----------------------------988921756836113674975210 Content-Disposition: form-data; name="File"; filename="matl.jpg" Content-Type: image/jpeg ÿØÿàJFIF`` ... ... ... ... ÿÛC P3ÿÙ ----------------------------988921756836113674975210--
P.S
上传文件的文件体中包含了文件名和文件类型信息
-
-
后端业务处理
MultipartFile
接口源码解析
-
MultipartFile
继承了InputStreamSource
接口 -
MultipartFile
封装了获取文件名称、源名称、文件类型等所有上传上来文件的所有信息 -
MultipartFile
可以通过transferTo
很方便的将文件输出到dest
file
中去,为我们将数据保存到本地提供了极大的便利
-
四、总结
-
前端采用
POST
请求,文件以二进制流的方式传输 -
后端拿到
MultipartFile
以后,通过MultipartFile
封装的方式直接获取文件所有信息并保存到本地磁盘