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

Snapan项目--预览文件梳理

整体思路

前端触发预览请求--->后端生成安全预览链接--->前端按文件类型适配渲染--->关闭预览

触发预览、前端请求预览链接

功能说明

用户点击文件预览按钮后,前端展示预览模态框并初始化加载状态。

核心代码【home.html】

动态生成文件列表时:

 <div class="action-item" onclick="previewFile('${file.filePath}')" data-tooltip="预览"><button class="action-icon preview">👁️</button></div>
    <!-- 预览模态框 --><div id="previewModal" class="modal" style="display: none;"><div class="modal-content" style="width: 90%; max-width: 1200px; height: 90vh; max-height: 900px; padding: 0;"><div class="modal-header"><h3 id="previewModalTitle">文件预览</h3><span class="close" onclick="closePreviewModal()">&times;</span></div><!-- 预览容器(放在模态框内) --><div id="previewContainer" style="width: 100%; height: calc(100% - 60px); border: none; border-radius: 0;"><div class="loading"><span>正在生成预览链接,请稍候...</span></div></div></div></div>

前端调用/api/filebase/getPreviewUrl接口,传递文件路径参数,处理成功/失败响应;

        // 1. 预览函数(点击预览按钮时调用)function previewFile(filePath) {// 显示预览模态框document.getElementById("previewModal").style.display = "flex";// 更新模态框标题(显示当前预览文件名)document.getElementById("previewModalTitle").textContent = `文件预览:${filePath.split("/").pop()}`;// 调用后端接口获取签名预览URL(使用你的项目基础路径)const baseUrl = "http://localhost:8080"; // 与你的后端地址一致$.ajax({url: `${baseUrl}/api/filebase/getPreviewUrl`,type: "GET",data: { filePath: filePath }, // 传递当前文件的OSS路径dataType: "json",success: function (res) {if (res.code === "200") {const previewUrl = res.previewUrl;const fileType = res.fileType;// 渲染预览内容renderPreview(previewUrl, fileType);console.log(filePath,fileType,previewUrl);} else {const container = document.getElementById("previewContainer");container.innerHTML = `<div class="error"><span>${res.msg || "生成预览链接失败,请重试"}</span></div>`;}},error: function (xhr, status, error) {const container = document.getElementById("previewContainer");container.innerHTML = `<div class="error"><span>预览接口访问失败:${error}</span><br><span style="margin-top:5px;display:inline-block;">请检查接口地址是否正确,或是否存在跨域问题</span></div>`;}});}

后端生成预览链接、前端渲染预览内容

功能说明

后端接收文件路径,处理oss域名,生成带有有效期的签名预览url,并提取文件类型。

核心代码

 /*** 获取文件预览的签名url* @param filePath oss文件中的路径* @return 包含url和文件类型的json*/@GetMapping("/getPreviewUrl")@ResponseBodypublic Map<String,String> getPreviewUrl(String filePath){Map<String,String> result=new HashMap<>();try{//生成1小时有效的签名url// 手动去除URL中的域名,只保留相对路径String ossDomain = "https://snapan.oss-cn-beijing.aliyuncs.com/";if (filePath.startsWith(ossDomain)) {filePath = filePath.substring(ossDomain.length()); // 截取后得到 "1761277048722.jpg"}// 生成签名URL(此时filePath是相对路径)String previewUrl=ossService.generatePreviewUrl(filePath,3600);System.out.println(previewUrl);System.out.println(filePath);//获取文件后缀String fileType=getFileSuffix(filePath);result.put("code","200");result.put("previewUrl",previewUrl);result.put("fileType",fileType);}catch (Exception e){result.put("code","500");result.put("msg","生成预览链接失败:"+e.getMessage());}return result;}//提取文件后缀private String getFileSuffix(String fileName){if(fileName.lastIndexOf(".")==-1){return "";//无后缀}return fileName.substring(fileName.lastIndexOf(".")+1).toLowerCase();}
/*** 生成带签名的预览URL(用于在线预览)*/public String generatePreviewUrl(String fileName, int expirationMinutes) {try {// 设置URL过期时间java.util.Date expiration = new java.util.Date();long expTimeMillis = expiration.getTime() + expirationMinutes * 60 * 1000;expiration.setTime(expTimeMillis);//创建响应头配置对象,控制浏览器是否预览ResponseHeaderOverrides headers=new ResponseHeaderOverrides();// 判断文件是否为PDF或Office文件,强制预览String lowerFileName = fileName.toLowerCase();if (lowerFileName.endsWith(".pdf") ||lowerFileName.endsWith(".doc") ||lowerFileName.endsWith(".docx") ||lowerFileName.endsWith(".xls") ||lowerFileName.endsWith(".xlsx") ||lowerFileName.endsWith(".ppt") ||lowerFileName.endsWith(".pptx")) {String fileNameOnly = fileName.substring(fileName.lastIndexOf("/") + 1);// 设置Content-Disposition为inline,允许浏览器预览headers.setContentDisposition("inline;filename=\"" + fileNameOnly + "\"");}//生成带响应头配置的签名urlcom.aliyun.oss.model.GeneratePresignedUrlRequest request=new com.aliyun.oss.model.GeneratePresignedUrlRequest(bucketName,fileName);request.setExpiration(expiration);request.setMethod(HttpMethod.GET);request.setResponseHeaders(headers);// 生成带签名的URL,用于预览(GET请求)java.net.URL signedUrl = ossClient.generatePresignedUrl(request);String urlStr=signedUrl.toString();return urlStr;} catch (Exception e) {throw new RuntimeException("生成预览URL失败", e);}}

前端根据文件类型(图片、视频、Office 文档等),生成对应的 HTML 标签渲染预览内容。

  /*** 4. 根据文件类型渲染不同的预览组件* @param {string} url - 后端返回的签名预览URL* @param {string} type - 后端返回的文件后缀(小写)*/function renderPreview(url, type) {const container = document.getElementById("previewContainer");container.innerHTML = ""; // 清空加载状态switch (type) {// 图片类型case "jpg": case "jpeg": case "png": case "gif": case "webp": case "bmp":container.innerHTML = `<img src="${url}" alt="图片预览" title="点击可查看原图" style="width:100%;height:100%;object-fit:contain;">`;break;// PDF类型/*case "pdf":container.innerHTML = `<iframe src="${url}" title="PDF预览" style="width:100%;height:100%;border:none;"></iframe>`;break;*/// 视频类型case "mp4":case "webm":case "mov":case "avi":case "mkv":container.innerHTML = `<video controls autoplay muted playsinline style="width:100%;height:100%;padding:20px;"><source src="${url}" type="video/${type}">您的浏览器不支持该视频格式,请下载后查看</video>`;break;// 音频类型case "mp3": case "wav": case "ogg": case "flac":container.innerHTML = `<audio controls autoplay style="width:100%;padding:20px;"><source src="${url}" type="audio/${type}">您的浏览器不支持该音频格式,请下载后查看</audio>`;break;// Office文档(依赖kkFileView)case "doc": case "docx": case "xls": case "xlsx": case "ppt": case "pptx":case "pdf":case "txt": case "md": case "json": case "xml": case "html": case "css": case "js":case "xmind":case "vsd":case "py":case "eml":case "psd":case "csv":const kkFileViewUrl = "http://101.42.40.144:8012";//const encodedUrl = encodeURIComponent(Base64.encode(url));const encodedUrl = encodeURIComponent(Base64.encode(url).replace(/[\r\n]/g, '')).replace(/%0A/g, '');const previewUrl = `${kkFileViewUrl}/onlinePreview?url=${encodedUrl}`;console.log("office预览地址:",previewUrl);container.innerHTML = `<iframesrc="${previewUrl}"title="Office文档预览"style="width:100%;height:100%;border:none;"onload="document.getElementById('officeLoading').style.display='none';this.style.display='block'"></iframe>`;break;// 其他类型default:showDownloadTip(container, url, type);}}function showDownloadTip(container, url, fileType) {container.innerHTML = `<div class="download-tip" style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;"><span>当前文件类型(.${fileType || "未知"})不支持在线预览</span><br></div>`;}
  • 图片直接用img标签,通过object-fit:contain保持比例;
  • 视频 / 音频使用原生video/audio标签,支持控制、自动播放(视频默认静音);
  • Office 文档等通过iframe嵌入第三方服务(kkFileView),需对 URL 进行 Base64 编码避免格式错误;

关闭预览

// 2. 新增:关闭预览模态框function closePreviewModal() {document.getElementById("previewModal").style.display = "none";// 清空预览容器,避免下次打开有残留document.getElementById("previewContainer").innerHTML = `<div class="loading"><span>正在生成预览链接,请稍候...</span></div>`;}

关于kkfileview安装及使用

参考了以下博客,感谢这位大佬

https://blog.csdn.net/qq_33697094/article/details/126076565?fromshare=blogdetail&sharetype=blogdetail&sharerId=126076565&sharerefer=PC&sharesource=2301_80391652&sharefrom=from_link

http://www.dtcms.com/a/557518.html

相关文章:

  • Readest0.9.90 | 一款好用的开源阅读器,提供划词翻译、高亮笔记、语音朗读等功能,内置大量朗读引擎和云同步
  • [Dify 实战] Dify 与 LangChain 的区别与组合方式:从工作流到编排框架的深度解析
  • internet网站建设试卷做兼职的网站打字员
  • 济南网站建设多少钱官方传奇手游下载
  • H.264 编码原理与 RTP/RTSP 传输流程详解
  • 包装设计的网站wordpress禁用导航栏代码
  • 非洲秃鹫优化算法(AVOA)的详细原理和数学公式
  • 怎样建立网站卖东西百度打开百度搜索
  • 淮安网站优化营销案例分享
  • 高效简便的网站开发网站服务器迁移
  • html5与android之间相互调用
  • 用一份 YAML 编排实时数据集成Flink CDC 工程实践
  • 全志SPI-NG框架使用说明
  • 域名及网站建设实训wordpress 不能自定义主题
  • 新河网站网站后台默认用户名
  • 第十二章:终极叩问:我是谁,我往何方?(1)
  • JAVA高频面试题
  • 如何制作一个自己的网站?安全教育平台登录入口网址
  • 软考 系统架构设计师系列知识点之杂项集萃(184)
  • Redis性能提升秘籍:大Key与热点Key优化实战
  • 大专物流管理专业职业发展指南
  • 徐州网站制作机构做猎头需要用到的网站
  • 石家庄做网站制作公司做公司点评的网站
  • Git指令集
  • 基于边缘信息提取的遥感图像开放集飞机检测方法
  • 前端基础知识---Promise
  • Java 基础——函数式编程
  • webkitx(Android WebView 最佳实践库)
  • 调查网站做调查不容易过横栏建设网站
  • 勐海县住房和城乡建设局网站南昌做网站费用