目录
在 Web 开发中,文件上传是一项常见且重要的功能,例如在用户更换头像或添加文章时常常需要用到。本文将详细介绍文件上传并存储到本地的功能实现步骤,以及相关代码解析,帮助读者理解这一功能的开发过程。
一、文件上传功能需求分析
- 用户操作场景
- 在用户更换头像或添加文章时,需要携带图片的 URL 访问地址。
- 用户通过前端界面选择要上传的文件,点击提交按钮后,将文件数据上传至服务器。
- 服务器功能需求
- 后台需要提供一个文件上传接口,接收前端提交的文件数据。
- 接口接收到文件后,将其存储到本地磁盘,并返回文件在本地的访问地址(此处先实现本地存储,后续再扩展到阿里云服务器存储)。
二、文件上传接口相关知识回顾
- 前端要素
- 请求方式必须为 POST。
- 表单的编码类型必须是
multipart/form-data
。 - 文件表单项对应的
type
类型必须是file
。
- 服务器端处理(基于 Spring MVC 框架)
- 可以在参数上声明一个
MultipartFile
类型的参数来接收上传的文件内容。 MultipartFile
提供了多个方法,如:getOriginalFileName
:获取原始文件的名字(用户本地存放的文件名字)。transferTo
:将接收到的文件转存到本地磁盘文件中。getSize
:获取文件的大小。getBytes
:获取文件内容的字节数组。getInputStream
:获取接收到的文件内容的输入流。
- 可以在参数上声明一个
三、文件上传接口实现步骤
(一)创建 Controller 类
- 在
control
包下创建一个名为FileUploadController
的类。- 在类上添加
@RestController
注解,使其成为一个控制器类,能够处理 HTTP 请求并返回响应数据。
- 在类上添加
- 在
FileUploadController
类中添加upload
方法。- 方法的返回值类型为
Result<String>
(假设Result
是自定义的响应结果封装类,泛型为String
,因为最终要返回给前端的是一个字符串,即文件的访问地址)。 - 方法名定义为
upload
。
- 方法的返回值类型为
(二)配置上传接口映射
- 在
upload
方法上添加@PostMapping("/upload")
注解。- 这表明该方法将处理路径为
/upload
的 POST 请求,与接口文档中的请求路径和方式保持一致。
- 这表明该方法将处理路径为
(三)接收上传文件参数
- 在方法的参数列表中声明一个参数,类型为
MultipartFile
,参数名定义为file
。- 这个参数将用于接收前端上传的文件数据。
(四)将文件存储到本地磁盘
- 使用
MultipartFile
的transferTo
方法将文件存储到本地磁盘。- 首先,确定文件存储的目录,例如在桌面上提前创建一个名为
files
的文件夹。 - 获取该文件夹的路径,在代码中可以通过复制路径并粘贴的方式获取(实际开发中可能会根据项目结构和配置来确定路径)。
- 构建存储文件的完整路径,包括文件名。这里需要注意文件名的处理,以避免文件覆盖问题。
- 原始代码中直接使用原始文件名可能导致同名文件覆盖,改进后的代码如下:
- 首先,确定文件存储的目录,例如在桌面上提前创建一个名为
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@RestController
public class FileUploadController {
@PostMapping("/upload")
public Result<String> upload(@RequestParam("file") MultipartFile file) {
try {
// 生成唯一文件名
String originalFileName = file.getOriginalFilename();
String fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));
String uniqueFileName = UUID.randomUUID().toString() + fileExtension;
// 构建文件存储路径(假设存储在项目根目录下的files文件夹中,实际可根据需求调整)
String filePath = "files/" + uniqueFileName;
File dest = new File(filePath);
file.transferTo(dest);
// 此处模拟返回文件访问地址,实际应根据存储情况生成正确地址
return Result.success("模拟URL访问地址:/" + uniqueFileName);
} catch (IOException e) {
e.printStackTrace();
return Result.error("文件上传失败");
}
}
}
在上述代码中,首先获取原始文件名,然后提取文件后缀名,接着使用UUID
生成唯一的文件名,最后将文件存储到指定路径下。
(五)响应前端数据
- 存储文件成功后,需要给前端响应数据。
- 返回一个包含成功状态码、提示信息和文件访问地址(此处为模拟地址,实际应根据文件存储位置和服务器配置生成正确地址)的
Result
对象。
- 返回一个包含成功状态码、提示信息和文件访问地址(此处为模拟地址,实际应根据文件存储位置和服务器配置生成正确地址)的
四、测试文件上传接口
- 使用 Postman 进行接口测试。
- 导入测试用例(如果有),确保测试用例中请求的方式为 POST,路径为
/upload
,请求参数格式为form-data
,且包含一个名为file
的文件类型参数。 - 先进行登录操作获取
token
,并将token
添加到文件上传测试用例的请求头或参数中(如果接口需要认证)。 - 选择要上传的文件,点击
Send
按钮发送请求。 - 查看响应结果,如果成功,应返回类似
{ "code": 200, "message": "操作成功", "data": "模拟URL访问地址:/[唯一文件名]" }
的信息。 - 同时,可以到本地存储文件的目录(如
files
文件夹)下查看文件是否成功存储,并且文件名是否为生成的唯一文件名。
- 导入测试用例(如果有),确保测试用例中请求的方式为 POST,路径为
通过以上步骤,实现了文件上传并存储到本地磁盘的功能,同时通过UUID
解决了文件覆盖问题,并能够正确响应前端数据,方便后续进一步扩展到将文件存储到阿里云服务器等功能。