文件上传接口设计
文件上传功能通常涉及前端传递文件数据到后端,后端接收并存储文件。设计时需考虑文件大小限制、文件类型校验、存储位置以及安全性。
接口路径: /api/upload 请求方法: POST 请求头: Content-Type: multipart/form-data 请求参数:
file: 文件数据(必填)uploadPath: 文件存储路径(可选,默认值由后端配置)
响应格式:
{
"success": boolean,
"message": string,
"data": {
"fileName": string,
"filePath": string,
"fileSize": number
}
}
后端实现(Spring Boot)
使用Spring Boot框架实现文件上传接口,主要依赖spring-boot-starter-web。
依赖配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
控制器代码:
@RestController
@RequestMapping("/api")
public class FileUploadController {
@Value("${file.upload-dir}")
private String uploadDir;
@PostMapping("/upload")
public ResponseEntity<Map<String, Object>> uploadFile(
@RequestParam("file") MultipartFile file,
@RequestParam(value = "uploadPath", required = false) String uploadPath) {
Map<String, Object> response = new HashMap<>();
try {
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
Path directory = Paths.get(uploadDir, uploadPath != null ? uploadPath : "");
Files.createDirectories(directory);
Path filePath = directory.resolve(fileName);
Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
response.put("success", true);
response.put("message", "File uploaded successfully");
response.put("data", Map.of(
"fileName", fileName,
"filePath", filePath.toString(),
"fileSize", file.getSize()
));
return ResponseEntity.ok(response);
} catch (Exception e) {
response.put("success", false);
response.put("message", "Failed to upload file: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
}
配置文件:
# application.properties
file.upload-dir=uploads
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
前端实现(HTML + JavaScript)
前端通过表单提交文件数据,使用FormData对象包装文件。
HTML表单:
<form id="uploadForm" enctype="multipart/form-data">
<input type="file" name="file" id="fileInput">
<input type="text" name="uploadPath" placeholder="Optional storage path">
<button type="submit">Upload</button>
</form>
<div id="result"></div>
JavaScript代码:
document.getElementById('uploadForm').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData();
const fileInput = document.getElementById('fileInput');
const uploadPath = e.target.elements.uploadPath.value;
formData.append('file', fileInput.files[0]);
if (uploadPath) formData.append('uploadPath', uploadPath);
try {
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
const result = await response.json();
document.getElementById('result').innerHTML = JSON.stringify(result, null, 2);
} catch (error) {
console.error('Upload failed:', error);
}
});
安全性增强
文件类型校验: 在控制器中添加校验逻辑,避免上传恶意文件。
String contentType = file.getContentType();
if (!Arrays.asList("image/jpeg", "image/png").contains(contentType)) {
response.put("success", false);
response.put("message", "Only JPEG/PNG files are allowed");
return ResponseEntity.badRequest().body(response);
}
文件名处理: 避免路径遍历攻击,确保文件名安全。
String fileName = file.getOriginalFilename();
if (fileName.contains("..")) {
response.put("success", false);
response.put("message", "Invalid file name");
return ResponseEntity.badRequest().body(response);
}
存储优化
分块上传: 大文件可采用分块上传,减少内存占用。
@PostMapping("/upload-chunk")
public ResponseEntity<?> uploadChunk(
@RequestParam("chunk") MultipartFile chunk,
@RequestParam("chunkNumber") int chunkNumber,
@RequestParam("totalChunks") int totalChunks,
@RequestParam("identifier") String identifier) {
// 实现分块合并逻辑
}
云存储集成: 可扩展为AWS S3或阿里云OSS存储。
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().build();
s3Client.putObject("bucket-name", "file-key", file.getInputStream(), null);
1962

被折叠的 条评论
为什么被折叠?



