package com.test.bijihoudaun.controller; import cn.hutool.core.util.StrUtil; import com.test.bijihoudaun.common.response.R; import com.test.bijihoudaun.entity.Image; import com.test.bijihoudaun.service.ImageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.List; @Tag(name = "markdown接口") @RestController @RequestMapping("/api/images") public class ImageController { @Value("${file.upload-dir}") private String rootPath; @Autowired private ImageService imageService; @Operation(summary = "上传图片") @PostMapping public R uploadImage( @RequestPart("file") MultipartFile file, @RequestParam(value = "userId", required = false) Long userId, @RequestParam(value = "markdownId", required = false) Long markdownId) { try { Image image = imageService.uploadImage(file, userId, markdownId); return R.success(image); } catch (IOException e) { return R.fail(); } } @Operation(summary = "根据id删除图片") @PostMapping("/{id}") public R deleteImage(@PathVariable Long id) { boolean result = imageService.deleteImage(id); if (result) { return R.success(); } else { return R.fail(); } } /** * 在线预览(图片、视频、音频、pdf 等浏览器可直接识别的类型) */ @GetMapping("/preview/{url}") @Operation(summary = "在线预览", description = "浏览器直接打开文件流") public void preview(@PathVariable String url, HttpServletResponse resp) throws IOException { if (StrUtil.isBlank(url)) { resp.setStatus(404); R.fail("文件不存在"); } File file = new File(rootPath + File.separator + url); if (!file.exists()) { resp.setStatus(404); R.fail("文件不存在"); } String contentTypeFromFileExtension = getContentTypeFromFileExtension(url); // 设置正确的 MIME resp.setContentType(contentTypeFromFileExtension); // 设置文件长度,支持断点续传 resp.setContentLengthLong(file.length()); // 写出文件流 try (FileInputStream in = new FileInputStream(file)) { StreamUtils.copy(in, resp.getOutputStream()); } } @Operation(summary = "根据url删除图片") @PostMapping("/deleteByUrl") public R deleteImageByUrl(@RequestParam String url) { boolean result = imageService.deleteImageByUrl(url); if (result) { return R.success(); } else { return R.fail(); } } @Operation(summary = "根据url批量删除图片") @PostMapping("/batch") public R deleteImageByUrls(@RequestBody List urls) { boolean result = imageService.deleteImageByUrls(urls); if (result) { return R.success(); } else { return R.fail(); } } /** * 根据文件扩展名获取内容类型 * @param fileName 文件名 * @return 对应的MIME类型 */ private String getContentTypeFromFileExtension(String fileName) { if (StrUtil.isBlank(fileName) || !StrUtil.contains(fileName, '.')) { return "application/octet-stream"; } String extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase(); switch (extension) { case "jpg": case "jpeg": return "image/jpeg"; case "png": return "image/png"; case "gif": return "image/gif"; case "bmp": return "image/bmp"; case "webp": return "image/webp"; case "svg": return "image/svg+xml"; default: return "application/octet-stream"; } } }