Spring Boot MVC实现对象序列化下载及反序列化上传问题求解
Spring Boot MVC 实现Java序列化文件导出/导入完整方案
Web场景下不要沿用本地Java程序写死磁盘路径的序列化逻辑,服务端无法直接操作用户本地磁盘,序列化/反序列化逻辑直接对接HTTP请求/响应的IO流即可,不需要在服务端磁盘生成临时文件。
1. 前置准备
确保需要序列化的实体类实现Serializable接口,固定序列化版本号,避免后续类结构修改导致旧文件反序列化失败:
import java.io.Serializable; public class SavedGame implements Serializable { // 固定版本号,不要随意修改 private static final long serialVersionUID = 1L; private String info1; private String info2; private String info3; public SavedGame(String info1, String info2, String info3) { this.info1 = info1; this.info2 = info2; this.info3 = info3; } // 自行补充getter、setter }
2. 功能一:序列化对象导出到用户本地
点击按钮触发下载时,浏览器会自动弹出本地路径保存窗口,用户选择路径后文件会直接存入对应位置。
后端接口实现
直接把序列化输出流对接HTTP响应的输出流,设置下载响应头即可:
import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.io.ObjectOutputStream; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @RestController public class SerializeController { @GetMapping("/export/save") public void exportSavedGame(HttpServletResponse response) throws Exception { // 替换为你实际业务中需要序列化的对象 SavedGame savedGame = new SavedGame("存档1", "进度80%", "道具全收集"); // 设置响应头,告知浏览器当前响应是文件下载请求 response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); String fileName = URLEncoder.encode("game_save.ser", StandardCharsets.UTF_8); response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName); response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION); // 序列化逻辑直接对接响应输出流,不需要写入服务端本地磁盘 try (ObjectOutputStream oos = new ObjectOutputStream(response.getOutputStream())) { oos.writeObject(savedGame); oos.flush(); } } }
前端代码
不需要复杂逻辑,按钮点击直接访问下载接口即可:
<button id="exportBtn" class="primary">导出存档文件</button> <script> document.getElementById('exportBtn').addEventListener('click', () => { window.location.href = '/export/save'; }); </script>
3. 功能二:上传本地序列化文件反序列化为对象
后端接口实现
直接读取上传文件的输入流做反序列化,不需要把上传文件保存到服务端磁盘:
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import java.io.ObjectInputStream; // 可和上面的导出方法放在同一个Controller中 @PostMapping("/import/save") public String importSavedGame(@RequestParam("file") MultipartFile file) throws Exception { // 基础格式校验 String originalFilename = file.getOriginalFilename(); if (originalFilename == null || !originalFilename.endsWith(".ser")) { return "文件格式错误,请上传.ser格式的存档文件"; } // 直接从上传流反序列化 try (ObjectInputStream ois = new ObjectInputStream(file.getInputStream())) { SavedGame savedGame = (SavedGame) ois.readObject(); // 这里写拿到对象后的业务逻辑:存库、更新内存状态等 System.out.println("导入存档成功:" + savedGame.getInfo1()); return "存档导入成功"; } catch (ClassCastException e) { return "文件内容不合法,不是有效存档文件"; } }
前端代码
基于你提供的表单改造,拦截默认提交行为,用FormData上传文件即可:
<form id="singleUploadForm" name="singleUploadForm"> <input id="singleFileUploadInput" type="file" name="file" class="file-input" accept=".ser" required /> <button type="submit" class="primary submit-btn">导入存档</button> </form> <script> const form = document.getElementById('singleUploadForm'); form.addEventListener('submit', async (e) => { e.preventDefault(); const file = document.getElementById('singleFileUploadInput').files[0]; if (!file) { alert('请先选择要导入的文件'); return; } const formData = new FormData(); formData.append('file', file); const res = await fetch('/import/save', { method: 'POST', body: formData }); alert(await res.text()); form.reset(); }); </script>
补充配置
如果你的序列化文件大小超过Spring Boot默认的1MB上传限制,在application.properties中添加以下配置调整阈值:
spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=10MB
注意:不要对来源不可信的文件做反序列化操作,存在远程代码执行风险,公网接口建议额外增加文件签名、类白名单校验逻辑。
内容的提问来源于stack exchange,提问作者Vindie
相关产品推荐
相关产品推荐

