跳转至

PreviewDownloadController(预览/下载)

cn.myapps.converter.controller.PreviewDownloadController

预览与下载控制器,提供转换后文件的存在性校验、KMS 转换文件下载、runtime 预览格式下载(含文件加密检测与解密、路径规范化与目录穿越防护)。基址为 converter 模块的 context-path 占位符 ${myapps.context-path.converter:}(无 /api/rest 前缀)。

  • 接口类型:REST 资源
  • 类级注解@RestController@Tag(name = "Preview控制器")
  • 基址${myapps.context-path.converter:}
  • 鉴权:见 index.md 鉴权说明(无 token 强校验;但下载类端点需携带 accessToken 以派生 DES 解密密钥)

1. 校验文件是否存在

校验指定相对路径下的文件是否存在,含目录穿越防护(必须位于 <storageRoot>/uploads/ 规范路径下)。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/api/preview/isFileExisted(完整:${myapps.context-path.converter:}/api/preview/isFileExisted
  • 鉴权:否(无 token 强校验)
  • Tag:Preview控制器

请求参数

参数名 位置 类型 必填 说明
filepath query string 文件相对路径,将以 ISO-8859-1 解码后拼接到 Environment.getStorageRootPath() 之后;若已加密会先解密

请求示例

GET /api/preview/isFileExisted?filepath=%2Fuploads%2F2024%2Fdoc.pdf HTTP/1.1

响应

结构:统一 Resource(见 ../index.md「统一响应结构」)。data 恒为 null,信息在 errmsg。注意 errcode 取值非标(200=成功、500=各类失败)。

errcode errmsg 含义
200 文件存在! 文件存在
500 编码类型错误! URLDecoder 不支持 ISO-8859-1
500 文件路径或类型不合法! 解析后路径不在 <storageRoot>/uploads/ 规范目录下
500 文件不存在! 文件不存在

成功示例

{ "errcode": 200, "errmsg": "文件存在!", "data": null }

失败示例

{ "errcode": 500, "errmsg": "文件路径或类型不合法!", "data": null }


2. KMS 转换文件下载

下载 KMS 主题转换后的目标文件(路径位于 <storageRoot>/convert/pdf/kms/.objects/)。响应为二进制流。

  • 接口类型:REST 资源(二进制响应)
  • 请求方式GET
  • 请求路径/api/kms/converted/download(完整:${myapps.context-path.converter:}/api/kms/converted/download
  • 鉴权:见 index.md 鉴权说明需 accessToken:filepath 经 DesUtil.decryptTextByUserId(filepath, getUserId(request)) 解密,userId 取自 Security.getUserIdFromToken(request)
  • Tag:Preview控制器

请求参数

参数名 位置 类型 必填 说明
filepath query string 已加密的文件相对路径;先用当前用户 id 作为 DES 密钥解密,再拼接到 <storageRoot>/convert/pdf/kms/.objects/ 之后
filename query string 文件名(含扩展名),用于推导目标扩展名、设置响应 MIME 与下载文件名
watermarkStr query string 水印文本(参数声明但当前实现未实际写入水印)

请求示例

GET /api/kms/converted/download?filepath=<DES密文>&filename=doc.pdf HTTP/1.1

响应

结构:二进制流(成功时由 FileUtil.getMimeType(realFilePath) 推断 Content-Type,如 application/pdf;响应体为文件字节流)。

失败示例(写入纯文本错误,HTTP 状态仍 200):

Error: file path illegal!
找不到指定文件

触发条件 响应体文本
解析后路径不在 <storageRoot>/convert/pdf/ 规范目录下 Error: file path illegal!
文件不存在 找不到指定文件
文件名包含特殊符号(SecurityURL.simpleSpecialSymbols(filename) 校验失败) 空响应体(不下发)

路径安全:实现使用 SecurityFile.resolveFile(...).getCanonicalFile()convert/pdf/ 规范目录前缀比对,避免目录穿越;若文件已加密(FileEncryptAndDecrypt.isEncrypt),先解密到临时文件再输出,输出完成后删除解密临时文件


3. Runtime 预览格式下载

下载 runtime 主题转换后的目标文件(路径位于 <storageRoot>/convert/pdf/)。响应为二进制流。

  • 接口类型:REST 资源(二进制响应)
  • 请求方式GET
  • 请求路径/api/runtime/converted/download(完整:${myapps.context-path.converter:}/api/runtime/converted/download
  • 鉴权:见 index.md 鉴权说明需 accessToken:filepath 经 DesUtil.decryptTextByUserId(filepath, getUserId(request)) 解密,userId 取自 Security.getUserIdFromToken(request)
  • Tag:Preview控制器

请求参数

参数名 位置 类型 必填 说明
filepath query string 已加密的文件相对路径;先用当前用户 id 作为 DES 密钥解密,再拼接到 <storageRoot>/convert/pdf/ 之后
filename query string 文件名(含扩展名),用于推导目标扩展名、设置响应 MIME 与下载文件名
watermarkStr query string 水印文本(参数声明但当前实现未实际写入水印)

请求示例

GET /api/runtime/converted/download?filepath=<DES密文>&filename=doc.pdf HTTP/1.1

响应

结构:二进制流(成功时 Content-TypeFileUtil.getMimeType(realFilePath) 推断;响应体为文件字节流)。

失败示例(写入纯文本错误,HTTP 状态仍 200):

Error: file path illegal!
找不到指定文件

触发条件 响应体文本
解析后路径不在 <storageRoot>/convert/pdf/ 规范目录下 Error: file path illegal!
文件不存在 找不到指定文件
文件名包含特殊符号 空响应体(不下发)

该端点与 doFileDownload(KMS)逻辑结构相同,区别仅在于文件落盘目录:本端点为 <storageRoot>/convert/pdf/<filepath>,KMS 端点为 <storageRoot>/convert/pdf/kms/.objects/<filepath>