MultipartFile 上传、删除文件到静态资源服务器

本文介绍如何使用MultipartFile进行文件上传和删除操作。首先,讲解了MultipartFile作为文件上传接口的使用,包括前端上传和后端接收。接着,详细阐述了多文件与单文件上传的service调用方法。最后,提到了文件删除的实现,但未具体涉及service方法的实现细节。

第一步 首先是要文件传输,类似于文件传输的代码网上一大把

/**
	 * 上传文件到静态资源服务器
	 * @param fileType 文件类型(1:图片;2:文件;3:语音)
	 * @param is 图片文件流
	 * @param filename 文件名
	 * @param fileDir 文件目录(模块名/功能名;如:"usercenter/user")
	 * @param isResize 是否压缩图片
	 * @param subFileName 子文件名
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String uploadFileToServer(String fileType, InputStream is, String filename, String fileDir,
			boolean isResize, String subFileName) {
		String res = "";
		HttpURLConnection conn = null;
		// boundary就是request头和上传文件内容的分隔符
		String BOUNDARY = "--------------------------------";
		try {
			String urlType = "";
			if ("1".equals(fileType)) {
				urlType = UPLOAD_IMAGE;
			} else if ("2".equals(fileType)) {
				urlType = UPLOAD_FILE;
			} else if ("3".equals(fileType)) {
				urlType = UPLOAD_VOICE;
			}
			URL url = new URL(getServerUploadUrl() + urlType);
			conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(30000);
			conn.setReadTimeout(30000);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
			conn.setRequestProper
在 Java 中实现文件上传服务器,通常可以通过 Spring Boot 框架结合 `MultipartFile` 类来完成。以下是一个完整的示例,包括后端文件接收、存储以及通过 URL 访问的功能。 ### 文件上传服务实现 ```java import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.nio.file.*; @Service public class FileServiceImpl { @Value("${file.upload-dir}") private String filePath; public String uploadFile(MultipartFile file) throws IOException { // 确保上传目录存在 Path uploadPath = Paths.get(filePath); if (!Files.exists(uploadPath)) { Files.createDirectories(uploadPath); } // 构建文件存储路径 Path filePath = uploadPath.resolve(file.getOriginalFilename()); // 将上传文件写入目标路径 Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING); // 返回文件访问路径 return "/files/" + file.getOriginalFilename(); } } ``` ### 控制器类实现文件上传接口 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/api/files") public class FileUploadController { @Autowired private FileServiceImpl fileService; @PostMapping("/upload") public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) { try { String fileAccessUrl = fileService.uploadFile(file); return ResponseEntity.ok(fileAccessUrl); } catch (IOException e) { e.printStackTrace(); return ResponseEntity.status(500).body("File upload failed"); } } } ``` ### 配置静态资源访问路径 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired FileServiceImpl fileService; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/files/**") .addResourceLocations("file:" + fileService.getFilePath()); } } ``` ### application.properties 配置 ```properties file.upload-dir=/path/to/upload/directory ``` ### 前端上传示例(HTML + JavaScript) ```html <!DOCTYPE html> <html> <head> <title>File Upload</title> </head> <body> <h2>Upload File</h2> <form id="uploadForm"> <input type="file" name="file" id="fileInput" /> <button type="button" onclick="uploadFile()">Upload</button> </form> <script> function uploadFile() { const fileInput = document.getElementById('fileInput'); const file = fileInput.files[0]; const formData = new FormData(); formData.append('file', file); fetch('/api/files/upload', { method: 'POST', body: formData }) .then(response => response.text()) .then(url => { alert('File uploaded successfully: ' + url); }) .catch(error => { console.error('Error uploading file:', error); alert('File upload failed'); }); } </script> </body> </html> ``` ### 大文件分块上传实现思路 对于大文件上传,建议采用分块上传(Chunked Upload)的方式,将文件切分为多个小块进行上传,最后在服务器端合并。前端可以使用 `WebUploader` 或 `Resumable.js` 来实现分块上传,后端则需要支持接收分块并进行合并操作。 #### 分块上传后端处理示例(简化版) ```java @PostMapping("/upload-chunk") public ResponseEntity<String> handleChunkUpload( @RequestParam("fileId") String fileId, @RequestParam("chunkIndex") int chunkIndex, @RequestParam("totalChunks") int totalChunks, @RequestParam("chunk") MultipartFile chunk) { Path chunkDir = Paths.get("/path/to/chunks", fileId); if (!Files.exists(chunkDir)) { try { Files.createDirectories(chunkDir); } catch (IOException e) { return ResponseEntity.status(500).body("Failed to create chunk directory"); } } Path chunkPath = chunkDir.resolve("chunk-" + chunkIndex); try { Files.copy(chunk.getInputStream(), chunkPath, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { return ResponseEntity.status(500).body("Failed to save chunk"); } if (chunkIndex == totalChunks - 1) { // 所有分块上传完成,合并文件 Path finalFilePath = Paths.get("/path/to/upload/directory", fileId + ".mp4"); try (FileChannel outChannel = FileChannel.open(finalFilePath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) { for (int i = 0; i < totalChunks; i++) { Path currentChunkPath = chunkDir.resolve("chunk-" + i); try (FileChannel inChannel = FileChannel.open(currentChunkPath, StandardOpenOption.READ)) { outChannel.transferFrom(inChannel, outChannel.size(), Long.MAX_VALUE); } Files.deleteIfExists(currentChunkPath); // 删除分块文件 } } catch (IOException e) { return ResponseEntity.status(500).body("Failed to merge chunks"); } try { Files.deleteIfExists(chunkDir); // 删除分块目录 } catch (IOException e) { e.printStackTrace(); } return ResponseEntity.ok("/files/" + fileId + ".mp4"); } return ResponseEntity.ok("Chunk " + chunkIndex + " uploaded"); } ``` ### 文件上传支持 对于文件上传,前端可以使用 `<input type="file" webkitdirectory>` 来支持目录选择,后端则需要递归处理多个文件路径并保留目录结构。例如: ```html <input type="file" name="folder" id="folderInput" webkitdirectory /> ``` 后端可以遍历所有上传文件,并根据其相对路径构建对应的目录结构进行存储。 ### 文件加密上传 如果需要对文件进行加密上传,可以在文件写入磁盘前使用加密算法(如 AES)对文件内容进行加密: ```java import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.security.Key; import java.util.Base64; public class FileEncryptor { private static final String ALGORITHM = "AES"; private static final String KEY = "1234567890123456"; // 16 bytes key public static byte[] encrypt(byte[] data) throws Exception { Key key = new SecretKeySpec(KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(data); } public static byte[] decrypt(byte[] encryptedData) throws Exception { Key key = new SecretKeySpec(KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(encryptedData); } } ``` 在文件上传时调用加密方法: ```java byte[] encryptedData = FileEncryptor.encrypt(file.getBytes()); Files.write(filePath, encryptedData); ``` ### 文件下载实现 ```java @GetMapping("/download/{filename:.+}") public ResponseEntity<Resource> downloadFile(@PathVariable String filename) throws IOException { Path filePath = Paths.get(fileService.getFilePath()).resolve(filename); Resource resource = new UrlResource(filePath.toUri()); if (resource.exists() || resource.isReadable()) { return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .body(resource); } else { throw new RuntimeException("Could not read the file!"); } } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值