一个偏门的小问题

145 阅读2分钟

问题描述

我们公司给office文件加上了权限控制,导致这些文件无法被我们公司那些系统的程序读取,只有在把权限设置成public时才能正确读取。所以我需要实现一个校验功能,在用户上传文件时要能够识别权限是不是public,还得纯前端实现。

Pasted image 20250616135946.png

Pasted image 20250616140221.png

解决方法

我的助手ds告诉我,这个叫IRM(信息权限管理),并且提供了一个方案,就是使用jszip这个库去解析docx、pptx、xlsx这些文件,大家可能不知道,这些文件其实都是可以解压缩,只要把后缀一改就行,当然我们使用jszip的时候就不用改文件名后缀了。

具体代码

我这里使用的是cdn引入,大家也可以使用npm安装

  • cdn
<script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>
  • npm
npm i jszip

接下来我们要做的就很简单了,我们只用使用jszip去尝试解析文件,如果能解析,那就是没设置权限的,不能解析,就是设置了权限的。

这个一个简单的demo.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>
</head>

<body>
    <input type="file"/>
</body>

<script>

const jszip = new JSZip();

async function hasIRM(file) {
  try {
    const arrayBuffer = await file.arrayBuffer();
    const zip = await jszip.loadAsync(arrayBuffer);
    return false;
  } catch (e) {
    console.error("解压失败,可能被加密", e);
    return true;
  }
}

// 上传事件监听
document.querySelector('input[type="file"]').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  if (file) {
    const isIRMProtected = await hasIRM(file);
    console.log(`文件受IRM保护: ${isIRMProtected}`);
    // 根据结果提示用户或限制上传
  }
});
</script>

</html>

需要注意的是,设置了权限的文件其实是可以手动解压的,解压后的结果如下

Pasted image 20250616141859.png 这是没设置权限的文件解压后的结果

Pasted image 20250616142028.png 可以发现设置权限的文件有个文件叫EncryptedPackage,这个或许也可以作为判断是否有设置权限的依据,只是不知道为什么jszip无法正确读取并解压。