在Web开发中,文件上传是一个常见的功能需求。Spring框架提供了MultipartFile接口,用于处理文件上传请求。MultipartFile可以代表一个多部分文件上传请求中的一个文件,提供了一系列方法用于获取文件的各种属性和内容,使得在后端处理文件上传变得十分方便。下面我们将介绍MultipartFile在Web应用中的几种常见使用场景。
1. 图片上传
在Web应用中,图片上传是一种常见的场景。用户需要上传头像、相片、证件照等图片文件,而后端需要接收并保存这些文件。使用MultipartFile接口可以轻松地实现图片文件的接收和处理。通过获取文件的原始文件名、内容类型、大小等属性,我们可以实现对图片文件的有效管理和存储。例如,我们可以将图片文件保存到服务器的文件系统中,或者将其存储到云存储服务中。
2. 文件下载
除了文件上传,文件下载也是Web应用中常见的功能需求。使用MultipartFile接口,我们可以实现文件的下载功能。在服务器端,我们可以将文件作为MultipartFile对象进行处理,并通过设置响应头信息,将文件作为下载内容返回给客户端。客户端接收到文件后,可以将其保存到本地磁盘或进行其他处理。
3. 文件编辑
在Web应用中,有时候用户需要对上传的文件进行编辑操作,例如修改文件名、修改文件内容等。使用MultipartFile接口,我们可以实现对文件的编辑功能。首先,我们可以通过MultipartFile接口获取上传的文件对象,然后对其进行相应的编辑操作。例如,我们可以修改文件的名称、修改文件的内容等。编辑完成后,我们可以将修改后的文件保存到服务器或返回给客户端。
4. 文件预览和展示
在Web应用中,有时候我们需要将上传的文件进行预览或展示。例如,在文档管理系统中,用户需要预览或下载文档文件。使用MultipartFile接口,我们可以实现文件的预览和展示功能。我们可以将文件作为MultipartFile对象进行处理,然后将其内容转换为适当的格式进行展示。例如,对于PDF文件,我们可以使用PDF阅读器插件进行展示;对于图片文件,我们可以将其直接展示在网页上。
5. 文件批量上传和处理
在实际应用中,有时候用户需要批量上传多个文件,并对这些文件进行处理。使用MultipartFile接口,我们可以实现文件的批量上传和处理功能。我们可以将多个文件作为一个多部分文件上传请求进行处理,然后对每个文件进行相应的操作。例如,我们可以将多个图片文件批量上传到服务器,并对它们进行压缩、裁剪等处理。
package com.javagpt.back.controller; import com.javagpt.application.context.UserAppContextHolder; import com.javagpt.application.file.FileApplicationService; import com.javagpt.application.file.FileDTO; import com.javagpt.common.annotation.RespSuccess; import com.javagpt.common.constant.EMConstant; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @Api(tags = "文件接口") @Slf4j @RestController @RequestMapping(EMConstant.API_V1 + "/file") @RespSuccess @RequiredArgsConstructor public class FileController { private final FileApplicationService fileApplicationService; @ApiOperation("通用文件上传") @PostMapping(value = "/uploadFile") public FileDTO uploadFile(@RequestParam("file") MultipartFile multipartFile) throws IOException { Long enterpriseId = UserAppContextHolder.getCurrentUser().getEnterpriseId(); FileDTO fileDTO = fileApplicationService.saveFile(enterpriseId, multipartFile); return fileDTO; } //@PreAuthorize("hasAuthority('mp:file:download')") @ApiOperation("下载文件") @GetMapping(value = "/downloadFile") public void download(@RequestParam(value = "id") Long id, HttpServletResponse response) throws IOException { fileApplicationService.downloadFile(response, id, UserAppContextHolder.getCurrentUser().getEnterpriseId()); } @ApiOperation("查看文件信息") @GetMapping(value = "/info") public FileDTO fileInfo(@RequestParam(value = "id") Long id) throws IOException { return fileApplicationService.findById(id); } @ApiOperation("下载视频") @GetMapping(value = "/downloadFile2") public void download2(@RequestParam(value = "id") Long id, HttpServletRequest request, HttpServletResponse response) throws IOException { fileApplicationService.downloadVideo(request, response, id, UserAppContextHolder.getCurrentUser().getEnterpriseId()); } }
package com.javagpt.application.file; import com.javagpt.common.exception.BusinessRuntimeException; import com.javagpt.common.oos.OssService; import com.javagpt.common.util.ModelUtils; import com.javagpt.common.util.SpringResponseUtils; import com.javagpt.file.entity.FileEntity; import com.javagpt.file.repository.FileRepository; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.*; @Service @Slf4j @RequiredArgsConstructor public class FileApplicationService { private final OssService ossService; private final FileRepository fileRepository; public FileDTO findById(Long id) { FileEntity fileEntity = fileRepository.findById(id); return ModelUtils.convert(fileEntity, FileDTO.class); } @Transactional public FileDTO saveFile(Long enterpriseId, MultipartFile file) { FileEntity fileEntity = saveFile(enterpriseId, file, null); return ModelUtils.convert(fileEntity, FileDTO.class); } @Transactional public FileEntity saveFile(Long enterpriseId, MultipartFile file, String fileName) { String originalFilename = file.getOriginalFilename(); String name = StringUtils.isBlank(fileName) ? FilenameUtils.getBaseName(originalFilename) : fileName; String suffix = FilenameUtils.getExtension(originalFilename); long size = file.getSize(); FileEntity fileEntity = new FileEntity(); fileEntity.setName(name).setSuffix(suffix).setSize(size).setEnterpriseId(enterpriseId); fileEntity = fileEntity.save(); String key = fileEntity.getPath(); InputStream inputStream = null; try { inputStream = file.getInputStream(); } catch (IOException e) { log.error("saveFile error:", e); throw BusinessRuntimeException.error("上传文件失败"); } ossService.uploadFile(inputStream, key); IOUtils.closeQuietly(inputStream); return fileEntity; } @Transactional public FileEntity saveFile(File file) { long size = file.length(); FileEntity fileEntity = new FileEntity(); String baseName = FilenameUtils.getBaseName(file.getName()); String extension = FilenameUtils.getExtension(file.getName()); fileEntity.setName(baseName).setSuffix(extension).setSize(size); fileEntity = fileEntity.save(); String key = fileEntity.getPath(); FileInputStream inputStream = null; try { inputStream = new FileInputStream(file); ossService.uploadFile(inputStream, key); } catch (FileNotFoundException e) { log.error("saveFile error:", e); throw BusinessRuntimeException.error("上传文件失败"); } IOUtils.closeQuietly(inputStream); return fileEntity; } public void downloadFile(HttpServletResponse response, Long fileId, Long enterpriseId) throws IOException { FileEntity fileEntity = fileRepository.findById(fileId); if (fileEntity == null) { throw BusinessRuntimeException.error("无效的文件Id"); } String key = fileEntity.getPath(); InputStream inputStream = ossService.downloadFile(key); SpringResponseUtils.writeAndFlushResponse(inputStream, response, fileEntity.fileFullName()); } public void downloadVideo(HttpServletRequest request, HttpServletResponse response, Long fileId, Long enterpriseId) throws IOException { FileEntity fileEntity = fileRepository.findById(fileId); if (fileEntity == null) { throw BusinessRuntimeException.error("无效的文件Id"); } response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes"); Long fileSize = fileEntity.getSize(); long start = 0, end = fileSize - 1; //判断前端需不需要分片下载 if (StringUtils.isNotBlank(request.getHeader("Range"))) { response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); String numRange = request.getHeader("Range").replaceAll("bytes=", ""); String[] strRange = numRange.split("-"); if (strRange.length == 2) { start = Long.parseLong(strRange[0].trim()); end = Long.parseLong(strRange[1].trim()); //若结束字节超出文件大小 取文件大小 if (end > fileSize - 1) { end = fileSize - 1; } } else { //若只给一个长度 开始位置一直到结束 start = Long.parseLong(numRange.replaceAll("-", "").trim()); } } long rangeLength = end - start + 1; String contentRange = new StringBuffer("bytes ").append(start).append("-").append(end).append("/").append(fileSize).toString(); response.setHeader(HttpHeaders.CONTENT_RANGE, contentRange); response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(rangeLength)); String key = fileEntity.getPath(); InputStream inputStream = ossService.downloadFile2(key, start, end); SpringResponseUtils.writeAndFlushResponse(inputStream, response, fileEntity.fileFullName()); } }
总之,MultipartFile接口在Web应用中具有广泛的应用场景,可以实现文件上传、下载、编辑、预览和批量处理等功能。通过熟练掌握MultipartFile接口的使用方法和技巧,我们可以更加高效地处理文件上传和下载请求,提升Web应用的用户体验和功能性能。
关注我,紧跟本系列专栏文章,咱们下篇再续!
作者简介:魔都技术专家,多家大厂后端一线研发经验,在分布式系统、和大数据系统等方面有多年的研究和实践经验,拥有从零到一的大数据平台和基础架构研发经验,对分布式存储、数据平台架构、数据仓库等领域都有丰富实践经验。
各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。
负责:
- 中央/分销预订系统性能优化
- 活动&优惠券等营销中台建设
- 交易平台及数据中台等架构和开发设计
- 车联网核心平台-物联网连接平台、大数据平台架构设计及优化
目前主攻降低软件复杂性设计、构建高可用系统方向。
参考: