作者:fyupeng
技术专栏:☞ https://github.com/fyupeng
项目地址:☞ https://github.com/fyupeng/distributed-blog-system-api
留给读者
开发人员往往会经常需要通过浏览器下载文件、图片或者PDF或者缩略图等,这时候我们可以根据自己的需求自定义设置,安全性就可以由自己来把握。
难点主要在于把文件路径当成参数传给后端,后端根据一定的规则处理,将结果写入响应返回给浏览器。
优点:
OSS
获取,本地没有先从OSS
下载到本地,以便频繁下载文件时降低OSS
的出入流量。/** * @Auther: fyp * @Date: 2024/7/26 * @Description: 文件预览处理器 * @Package: com.gwssi.common.web * @Version: 1.0 */ @Controller public class FilePreviewController { //本地测试可改为自己的路径 //private static final String FILE_DIRECTORY = "D:/upload/"; private static final String FILE_DIRECTORY = "/data/hqzr/"; @ResponseBody @RequestMapping(value = "/file/{fileUrl}/**", method = RequestMethod.GET) public void getFile(@PathVariable String fileUrl, HttpServletRequest req, HttpServletResponse resp) throws IOException { String path = req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString(); String path2 = req.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString(); String args = new AntPathMatcher().extractPathWithinPattern(path2, path); args = args.replace(".do", ""); fileUrl = fileUrl + "/" + args; File file = new File(FILE_DIRECTORY + fileUrl); byte[] bytes = null; // 添加安全检查,确保文件确实在预期的目录中 if (!file.exists() || !file.isFile() || !file.getCanonicalPath().startsWith(new File(FILE_DIRECTORY).getCanonicalPath())) { // 处理非法访问,例如返回404 File parentDir = file.getParentFile(); if (!parentDir.exists()) { parentDir.mkdirs(); // 确保文件所在的目录存在 } bytes = OssUtil.downloadByBytes(FILE_DIRECTORY + fileUrl); if (null != bytes) { FileOutputStream fos = new FileOutputStream(file); fos.write(bytes); fos.close(); resp.reset(); // 非常重要 } else { Map map = new HashMap(); map.put("code", "-100"); map.put("msg", "文件预览失败"); ResponseUtil.returnFrontByJSON(map, resp); } } // 设置适当的响应头(纯下载方式) //resp.setContentType("application/octet-stream; charset=utf-8"); //resp.setHeader("Content-Disposition", "attachment;filename=" + file.getName()); // 直接预览打开 resp.setContentType("image/png"); // 设置返回的文件类型 resp.addHeader("Content-Length", String.valueOf(file.length())); //文件大小 // 使用ServletOutputStream将图片数据写入响应 try (ServletOutputStream outputStream = resp.getOutputStream(); BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file))) { // 从文件服务器获取 if (null != bytes) { outputStream.write(bytes); } else { // 从本地获取 byte[] buffer = new byte[4096]; int bytesRead = -1; // 读取文件内容并写入响应 while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } // 刷新输出流,确保所有数据都被发送 outputStream.flush(); } } private String getMimeType(File file) { // 这里可以根据文件扩展名返回相应的MIME类型 // 这里只是一个简单的示例,实际应用中可能需要更复杂的逻辑 String filename = file.getName().toLowerCase(); if (filename.endsWith(".png")) { return MediaType.IMAGE_PNG_VALUE; } else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) { return MediaType.IMAGE_JPEG_VALUE; } // 添加更多MIME类型判断... return MediaType.APPLICATION_OCTET_STREAM_VALUE; // 默认类型 } }
简洁、高效、实用!
下一篇:VSCode切换默认终端