当前位置: 首页 > backend >正文

二、Web服务常用的I/O操作

一、单个或者批量上传文件

前端:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传示例</title><style>body {font-family: Arial, sans-serif;margin: 20px;line-height: 1.6;}button {padding: 10px 15px;background-color: #4CAF50;color: white;border: none;cursor: pointer;font-size: 16px;}button:hover {background-color: #45a049;}#result {margin-top: 20px;padding: 10px;border: 1px solid #ddd;background-color: #f9f9f9;}</style>
</head>
<body><h1>文件上传</h1><h2>单个文件上传</h2><form id="singleUploadForm"><input type="file" id="singleFileInput" name="file" required><button type="button" onclick="uploadSingleFile()">上传文件</button></form><h2>批量文件上传</h2><form id="batchUploadForm"><input type="file" id="batchFileInput" name="files" multiple required><button type="button" onclick="uploadBatchFiles()">上传文件</button></form><div id="result"></div><script>function uploadSingleFile() {const fileInput = document.getElementById('singleFileInput');const file = fileInput.files[0];if (!file) {alert('请选择一个文件');return;}const formData = new FormData();formData.append('file', file);fetch('http://localhost:8888/test/uploadFile', {method: 'POST',body: formData}).then(response => response.text()).then(data => {document.getElementById('result').innerHTML = data;}).catch(error => {document.getElementById('result').innerHTML = '上传失败: ' + error.message;});}function uploadBatchFiles() {const fileInput = document.getElementById('batchFileInput');const files = fileInput.files;if (!files || files.length === 0) {alert('请选择至少一个文件');return;}const formData = new FormData();for (let i = 0; i < files.length; i++) {formData.append('files', files[i]);}fetch('http://localhost:8888/test/uploadFiles', {method: 'POST',body: formData}).then(response => response.text()).then(data => {document.getElementById('result').innerHTML = data;}).catch(error => {document.getElementById('result').innerHTML = '上传失败: ' + error.message;});}</script>
</body>
</html>

在这里插入图片描述

后端:

 @PostMapping("test/uploadFile")public String upload(@RequestParam("file") MultipartFile file) {try {// 指定保存路径String savePath = "C:\\Users\\test\\Desktop\\";// 获取原始文件名String originalFilename = file.getOriginalFilename();if (originalFilename == null || originalFilename.isEmpty()) {return "文件名不能为空!";}// 构建完整路径Path targetPath = Paths.get(savePath + originalFilename);// 确保目录存在Files.createDirectories(targetPath.getParent());// 保存文件(替换已存在文件)Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);return "文件上传成功!保存路径: " + targetPath.toString();} catch (IOException e) {e.printStackTrace();return "文件上传失败: " + e.getMessage();}}@PostMapping("/test/uploadFiles")public String uploadFiles(@RequestParam("files") MultipartFile[] files) {try {String savePath = "C:\\Users\\test\\Desktop\\";List<String> uploadedFiles = Arrays.stream(files).map(file -> {try {String originalFilename = file.getOriginalFilename();if (originalFilename == null || originalFilename.isEmpty()) {return "文件名不能为空!";}Path targetPath = Paths.get(savePath + originalFilename);Files.createDirectories(targetPath.getParent());Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);return "文件上传成功!保存路径: " + targetPath.toString();} catch (IOException e) {return "文件上传失败: " + e.getMessage();}}).collect(Collectors.toList());return String.join("<br>", uploadedFiles);} catch (Exception e) {e.printStackTrace();return "文件上传失败: " + e.getMessage();}}

springboot要配置下文件上传大小限制:

# 设置单个文件的最大上传大小 (默认是1M)
spring.servlet.multipart.max-file-size=50MB
# 设置请求中所有文件的最大上传大小  (默认是10M)
spring.servlet.multipart.max-request-size=1000MB

二、后端上传文件

小文件处理,全部加载到内存

@GetMapping("/test/backUpload")public void backUpload() {String uploadUrl = "http://localhost:8888/test/uploadFile";String sourcePath = "C:\\Users\\test\\Desktop\\ttt\\666.txt";Path filePath = Paths.get(sourcePath);if (!Files.exists(filePath)) {System.out.println("文件不存在!");return;}try {byte[] fileBytes = Files.readAllBytes(filePath); // NIO读取文件内容到byte数组ByteArrayResource resource = new ByteArrayResource(fileBytes) {@Overridepublic String getFilename() {return filePath.getFileName().toString();}};HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.MULTIPART_FORM_DATA);MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();body.add("file", resource);HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);ResponseEntity<String> response = new RestTemplate().postForEntity(uploadUrl, requestEntity, String.class);System.out.println("上传结果:" + response.getBody());} catch (IOException e) {e.printStackTrace();}}

大文件处理使用webflux流式处理

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
 @GetMapping("/test/backUploadNew")public void backUploadNew() {String uploadUrl = "http://localhost:8888/test/uploadFile";String sourcePath = "C:\\Users\\test\\Desktop\\ttt\\666.txt";Path filePath = Paths.get(sourcePath);if (!Files.exists(filePath)) {System.out.println("文件不存在!");return;}try {InputStream inputStream = Files.newInputStream(filePath);InputStreamResource resource = new InputStreamResource(inputStream) {@Overridepublic String getFilename() {return filePath.getFileName().toString();}@Overridepublic long contentLength() throws IOException {return Files.size(filePath);}};MultipartBodyBuilder builder = new MultipartBodyBuilder();builder.part("file", resource).header("Content-Disposition", "form-data; name=file; filename=" + filePath.getFileName());HttpClient httpClient = HttpClient.create();ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);WebClient webClient = WebClient.builder().clientConnector(connector).build();webClient.method(HttpMethod.POST).uri(uploadUrl).contentType(MediaType.MULTIPART_FORM_DATA).bodyValue(builder.build()).retrieve().bodyToMono(String.class).doOnNext(result -> System.out.println("上传结果:" + result)).block(); // 等待上传完成} catch (IOException e) {e.printStackTrace();}}

三、前端下载文件

前端直接访问接口 /test/download 下载

@GetMapping("/test/download")public void download(HttpServletResponse response) throws IOException {// 文件路径Path filePath = Paths.get("C:\\Users\\test\\Desktop\\哈哈+ +c.txt"); // 替换成你的实际路径if (Files.exists(filePath)) {response.setContentType("application/octet-stream");String fileName = filePath.getFileName().toString();// 处理中文文件名:防止下载时乱码String encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-Disposition","attachment; filename=\"" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) + "\"; filename*=UTF-8''" + encodedFileName);// 直接用 Files.copy,拷贝文件到 response 的输出流Files.copy(filePath, response.getOutputStream());response.flushBuffer(); // 刷新缓冲区,确保数据发出去} else {response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件未找到!");}}

四、后端下载文件

@GetMapping("/test/backDownload")public void backDownload() {String url = "http://localhost:8888/test/download";String destinationPath = "C:\\Users\\test\\Desktop\\ttt\\666.txt";try {ResponseEntity<Resource> response =  new RestTemplate().getForEntity(url, Resource.class);if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {Path path = Paths.get(destinationPath);Files.createDirectories(path.getParent()); // 确保父目录存在Files.copy(response.getBody().getInputStream(), path);System.out.println("下载完成!");} else {System.out.println("下载失败,状态码:" + response.getStatusCode());}} catch (IOException e) {e.printStackTrace();}}
http://www.xdnf.cn/news/2412.html

相关文章:

  • HTML5 新特性详解:语义化标签、表单与音视频嵌入
  • pytorch写张量pt文件,libtorch读张量pt文件
  • 网络基础概念
  • HCIP知识点总结思维导图
  • Redis远程链接应用案例
  • 【计算机网络物理层】从信号传输到介质选型的核心技术解析
  • Web服务器技术选型指南:主流方案、核心对比与策略选择
  • 数据可视化 —— 饼图
  • 《MySQL 技术内幕-innoDB 存储引擎》笔记
  • 简述删除一个Pod流程?
  • HTTP:十二.HTTPS
  • UE 新建一个自带光照的场景
  • Git常用命令简明教程
  • 【每日随笔】文化属性 ① ( 天机 | 强势文化与弱势文化 | 文化属性的形成与改变 | 强势文化 具备的特点 )
  • 有源晶振输出匹配电阻选择与作用详解
  • AUTOSAR_Feature_Model_Analysis
  • 近期有哪些断链危机?如何提升供应链风险管理能力?
  • 头歌实训之游标触发器
  • 【Jupyter 启动时如何指定目录】
  • Android开机动画资源包制作(测试使用)
  • 数据库3,
  • 使用wavesurferJs实现录音音波效果
  • 突破常规:探索无 get 方法类设计的独特魅力
  • 1、Linux操作系统下,ubuntu22.04版本切换中英文界面
  • Spring security详细上手教学(三)密码管理
  • 基于STM32、HAL库的HX710A模数转换器ADC驱动程序设计
  • 【PyCharm- Python- ArcGIS】:安装一个和 ArcGIS 不冲突的独立 Python让PyCharm 使用 (解决全过程记录)
  • 树莓派超全系列教程文档--(44)如何在树莓派上编译树莓派内核
  • 详解 Unreal Engine(虚幻引擎)
  • 如何配置osg编译使支持png图标加载显示