想必你碰到这些情况:
哈哈大部分我们都会去干嘛呢?
作为计算机学者啊 肯定会想到一些这些坑爹收费的垃圾东西 我们自己搞搞
其实这不就是我们经常写过的文件上传下载业务吗
参考:https://www.cnblogs.com/gaodiyuanjin/p/18410900
结合博客园博主与统义灵码结合
图片插件依赖 <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.20</version> </dependency>
前页面显示: <!DOCTYPE html> <html lang="zh-CN"> <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; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f4f4f9; } .container { text-align: center; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } button { margin: 10px; padding: 10px 20px; font-size: 16px; cursor: pointer; } </style> </head> <body> <div class="container"> <h1>图片上传和下载</h1> <button id="uploadButton">上传图片</button> <button id="downloadButton">下载图片</button> <input type="file" id="fileInput" style="display:none;" accept="image/*"> <img id="previewImage" src="" alt="预览图片" style="display:none; max-width: 300px; margin-top: 20px;"> </div> <script> document.getElementById('uploadButton').addEventListener('click', function() { document.getElementById('fileInput').click(); }); document.getElementById('fileInput').addEventListener('change', function(event) { const file = event.target.files[0]; if (file) { const formData = new FormData(); formData.append('file', file); fetch('/api/images/upload', { method: 'POST', body: formData }) .then(response => response.text()) .then(message => { alert(message); if (message === "图片上传成功") { const reader = new FileReader(); reader.onload = function(e) { const img = document.getElementById('previewImage'); img.src = e.target.result; img.style.display = 'block'; }; reader.readAsDataURL(file); } }) .catch(error => console.error('Error:', error)); } }); document.getElementById('downloadButton').addEventListener('click', function() { const img = document.getElementById('previewImage'); if (img.src) { const filename = img.src.split('/').pop(); window.location.href = `/api/images/download/${filename}`; } else { alert('请先上传图片'); } }); </script> </body> </html>
业务controller package com.example.demo; import net.coobird.thumbnailator.Thumbnails; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Iterator; @RestController @RequestMapping("/api/images") public class ImageController { private static final String UPLOAD_DIR = "D:/zhaowenya/"; private static final int MAX_WIDTH = 380; // 最大宽度 private static final int MAX_HEIGHT = 640; // 最大高度 @PostMapping("/upload") public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file) { try { if (file.isEmpty()) { return ResponseEntity.badRequest().body("请选择一个文件"); } // 检查文件类型 if (!file.getContentType().startsWith("image")) { return ResponseEntity.badRequest().body("文件类型不支持"); } // 读取图片 BufferedImage originalImage = ImageIO.read(file.getInputStream()); // 调整图片大小 BufferedImage resizedImage = Thumbnails.of(originalImage) .size(MAX_WIDTH, MAX_HEIGHT) .keepAspectRatio(false) // 不保持宽高比 .outputFormat("jpg") // 指定输出格式 .asBufferedImage(); // 压缩图片到指定大小 File destFile = new File(UPLOAD_DIR, file.getOriginalFilename()); compressImageToSize(resizedImage, destFile, 20 * 1024); // 20 KB return ResponseEntity.ok("图片上传成功"); } catch (IOException e) { e.printStackTrace(); return ResponseEntity.status(500).body("上传失败"); } } @GetMapping("/download/{filename}") public ResponseEntity<Resource> downloadImage(@PathVariable String filename) { try { File file = new File(UPLOAD_DIR + filename); if (!file.exists()) { return ResponseEntity.notFound().build(); } Resource resource = new FileSystemResource(file); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .contentType(MediaType.IMAGE_JPEG) // 根据实际情况调整媒体类型 .body(resource); } catch (Exception e) { e.printStackTrace(); return ResponseEntity.status(500).body(null); } } private void compressImageToSize(BufferedImage image, File destFile, int targetSizeInBytes) throws IOException { float quality = 1.0f; // 初始质量 float minQuality = 0.1f; // 最小质量 float maxQuality = 1.0f; // 最大质量 byte[] compressedImageBytes; do { compressedImageBytes = compressImage(image, quality); quality -= 0.1f; // 减少质量以减小文件大小 } while (compressedImageBytes.length > targetSizeInBytes && quality >= minQuality); if (compressedImageBytes.length > targetSizeInBytes) { throw new IOException("无法将图片压缩到指定大小"); } try (FileOutputStream fos = new FileOutputStream(destFile)) { fos.write(compressedImageBytes); } } private byte[] compressImage(BufferedImage image, float quality) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg"); if (!writers.hasNext()) { throw new IOException("不支持的图片格式"); } ImageWriter writer = writers.next(); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(quality); try (ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) { writer.setOutput(ios); writer.write(null, new IIOImage(image, null, null), param); } finally { writer.dispose(); } return baos.toByteArray(); } }
通过上述你可以自定义去修改一些什么kb 宽高 保存位置 图片格式啊什么的
其实这些业务从来都是“大自然的搬运工” 只不过需要的是你持续不断愿意学习能力
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?