77681 10 hours ago
parent
commit
c61688bf5f

+ 5 - 0
gw-framework/src/main/java/com/goldenwater/framework/web/service/TokenService.java

@@ -218,6 +218,11 @@ public class TokenService
     private String getToken(HttpServletRequest request)
     {
         String token = request.getHeader(header);
+        if (StringUtils.isEmpty(token))
+        {
+            // 支持 URL 参数携带 token(iframe/img/video 等资源加载不带请求头)
+            token = request.getParameter("token");
+        }
         if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
         {
             token = token.replace(Constants.TOKEN_PREFIX, "");

+ 5 - 0
gw-slgc/src/main/java/com/goldenwater/slgc/service/efinder/IDocFileService.java

@@ -22,6 +22,11 @@ public interface IDocFileService {
      */
     void download(Long id, HttpServletResponse response);
 
+    /**
+     * 预览文件(内联显示)
+     */
+    void preview(Long id, HttpServletResponse response);
+
     /**
      * 上传文件
      */

+ 55 - 0
gw-slgc/src/main/java/com/goldenwater/slgc/service/impl/efinder/DocFileServiceImpl.java

@@ -68,6 +68,61 @@ public class DocFileServiceImpl implements IDocFileService {
         }
     }
 
+    /**
+     * 预览文件(内联显示,不触发下载)
+     */
+    @Override
+    public void preview(Long id, HttpServletResponse response) {
+        DocFile docFile = docFileMapper.selectById(id);
+        if (docFile == null || docFile.getPath() == null) {
+            return;
+        }
+        try {
+            String name = docFile.getName();
+            String ext = name != null && name.contains(".") ? name.substring(name.lastIndexOf(".") + 1).toLowerCase() : "";
+            String contentType = guessContentType(ext);
+            response.setContentType(contentType);
+            // inline: 浏览器内联展示,不强制下载
+            response.setHeader("Content-Disposition", "inline; filename=" + encodeName(name));
+            response.setHeader("Access-Control-Allow-Origin", "*");
+            FileUtils.writeBytes(docFile.getPath(), response.getOutputStream());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private String guessContentType(String ext) {
+        switch (ext) {
+            case "pdf": return "application/pdf";
+            case "png": return "image/png";
+            case "jpg": case "jpeg": return "image/jpeg";
+            case "gif": return "image/gif";
+            case "webp": return "image/webp";
+            case "bmp": return "image/bmp";
+            case "svg": return "image/svg+xml";
+            case "mp4": return "video/mp4";
+            case "webm": return "video/webm";
+            case "mp3": return "audio/mpeg";
+            case "wav": return "audio/wav";
+            case "txt": case "log": return "text/plain;charset=UTF-8";
+            case "html": case "htm": return "text/html;charset=UTF-8";
+            case "md": return "text/markdown;charset=UTF-8";
+            case "json": return "application/json;charset=UTF-8";
+            case "csv": return "text/csv;charset=UTF-8";
+            case "xml": return "text/xml;charset=UTF-8";
+            default: return "application/octet-stream";
+        }
+    }
+
+    private String encodeName(String name) {
+        if (name == null) return "file";
+        try {
+            return java.net.URLEncoder.encode(name, "UTF-8").replace("+", "%20");
+        } catch (Exception e) {
+            return "file";
+        }
+    }
+
     /**
      * 上传文件
      */

+ 1 - 1
gw-slgc/src/main/java/com/goldenwater/web/controller/efinder/DocFileController.java

@@ -61,7 +61,7 @@ public class DocFileController extends BaseController {
     @Operation(summary = "预览文件")
     @GetMapping("/preview/{id}")
     public void preview(@Parameter(description = "文件ID") @PathVariable Long id, HttpServletResponse response) {
-        docFileService.download(id, response);
+        docFileService.preview(id, response);
     }
 
     /**

+ 6 - 2
gw-ui/src/views/efinder/viewer.vue

@@ -57,6 +57,7 @@
 
 <script setup name="EfinderViewer">
 import { getFileInfo, downloadFile, pageOfficeSave } from "@/api/efinder/finder"
+import { getToken } from "@/utils/auth"
 
 const route = useRoute()
 const router = useRouter()
@@ -72,9 +73,12 @@ const error = ref(false)
 const errorMsg = ref("")
 
 const baseUrl = import.meta.env.VITE_SERVICE_BASE_TITLE
+// 直接用于 iframe/img/video src 的资源地址必须带 token(浏览器加载不携带请求头)
+const token = getToken()
+const tokenQuery = token ? "?token=" + encodeURIComponent(token) : ""
 
 const pdfUrl = computed(() => {
-  return baseUrl + "/efinder/file/preview/" + fileId.value
+  return baseUrl + "/efinder/file/preview/" + fileId.value + tokenQuery
 })
 
 function loadFile() {
@@ -90,7 +94,7 @@ function loadFile() {
     loadTextContent()
   } else {
     getFileInfo(fileId.value).then(response => {
-      fileUrl.value = baseUrl + "/efinder/file/preview/" + fileId.value
+      fileUrl.value = baseUrl + "/efinder/file/preview/" + fileId.value + tokenQuery
       if (!fileType.value) {
         const rawType = response.data.type ? response.data.type.toLowerCase() : ""
         if (rawType === "doc" || rawType === "docx") {