如何通过JavaScript在HTML页面展示.OFT与.MSG文件的内容及附件?
这个需求我之前帮客户落地过,核心就是三步搞定:从SharePoint拉取文件、解析Outlook的MSG/OFT格式、最后渲染成邮件样式的HTML页面。下面给你一步步拆解细节:
实现步骤拆解
1. 从SharePoint获取OFT/MSG文件内容
首先得把文件从SharePoint拿到本地(或内存中),这里有两种常用的靠谱方式:
- Microsoft Graph API(推荐):如果你的环境支持Graph,这是最标准的方案。先通过OAuth 2.0获取有效访问令牌,再调用接口下载文件内容:
要是你有文件的直接访问URL(比如GET https://graph.microsoft.com/v1.0/sites/{site-id}/drive/items/{item-id}/contenthttps://your-sharepoint-site.com/sites/xxx/Documents/file.msg),也可以直接发起GET请求,但要记得带上身份验证信息(Cookie或Bearer令牌)。 - SharePoint REST API(内部场景):如果是在SharePoint页面里开发(比如SPFx Web Part),可以用SP自带的REST API,它会自动处理身份验证:
GET https://your-sharepoint-site.com/sites/xxx/_api/web/GetFileByServerRelativeUrl('/sites/xxx/Documents/file.msg')/$value
2. 解析OFT/MSG文件的内容、附件和图片
Outlook的MSG/OFT是二进制格式,没法直接读,得用专门的解析库,分前后端两种场景:
后端(Node.js)场景
- 解析MSG/OFT:用
@kenjiuno/msgreader这个库,它能完美解析邮件正文、附件、带Content-ID的内嵌图片:
注:OFT本质是邮件模板,结构和MSG完全一致,用同一个库就能解析。const { MsgReader } = require('@kenjiuno/msgreader'); const fs = require('fs'); // 读取本地缓存的文件(或直接用API返回的Buffer) const buffer = fs.readFileSync('file.msg'); const msgReader = new MsgReader(buffer); const emailData = msgReader.getEmail(); // 提取关键数据 const htmlBody = emailData.bodyHtml; // 邮件HTML正文 const allAttachments = emailData.attachments; // 所有附件(含内嵌图片) const embeddedImages = allAttachments.filter(att => att.isEmbedded); // 筛选内嵌图片
前端(浏览器)场景
如果要纯前端解析,可以用msgreader的浏览器版本,通过CDN引入或打包到项目:
<script src="https://unpkg.com/@kenjiuno/msgreader@latest/dist/msgreader.min.js"></script> <script> // 通过fetch获取文件的ArrayBuffer fetch('your-sharepoint-file-url', { headers: { 'Authorization': 'Bearer ' + yourAuthToken } }) .then(res => res.arrayBuffer()) .then(buffer => { const msgReader = new MsgReader(new Uint8Array(buffer)); const emailData = msgReader.getEmail(); // 后续处理逻辑和后端一致 }); </script>
提醒:前端解析大文件(>10MB)可能会有性能问题,建议小文件用这种方式,大文件优先后端解析。
3. 处理内嵌图片并渲染HTML邮件
解析后拿到的HTML正文里,内嵌图片的引用是cid:xxx格式(比如<img src="cid:image001.png@01D8A7C3.12345678">),需要把这些cid替换成可访问的资源:
方案一:转Base64嵌入(适合小图片)
把内嵌图片转成Base64直接嵌入HTML,不用额外存储:
embeddedImages.forEach(img => { // 把二进制内容转成Base64 const base64 = btoa(String.fromCharCode(...new Uint8Array(img.content))); const mimeType = img.mimeType || 'image/png'; // 替换cid引用 htmlBody = htmlBody.replace(`cid:${img.contentId}`, `data:${mimeType};base64,${base64}`); });
方案二:上传到SharePoint用URL引用(适合大图片)
如果图片体积大,或者需要复用,可以把图片上传到SharePoint文档库,再用生成的URL替换cid:
// 封装上传图片到SharePoint的函数 async function uploadImageToSP(content, fileName) { const response = await fetch(`https://graph.microsoft.com/v1.0/sites/{site-id}/drive/items/{folder-id}:/${fileName}:/content`, { method: 'PUT', headers: { 'Authorization': 'Bearer ' + yourAuthToken, 'Content-Type': img.mimeType }, body: content }); const fileData = await response.json(); return fileData.webUrl; } // 批量替换cid for (const img of embeddedImages) { const imgUrl = await uploadImageToSP(img.content, img.fileName); htmlBody = htmlBody.replace(`cid:${img.contentId}`, imgUrl); }
4. 展示附件和最终HTML页面
最后把处理好的HTML正文渲染到页面,同时展示非内嵌的附件:
<!-- 邮件内容展示区 --> <div class="email-container" style="border:1px solid #eee; padding:20px; max-width:800px; margin:20px auto;"> <h3 style="margin-top:0;">${emailData.subject}</h3> <div class="email-body" style="margin:15px 0;">${htmlBody}</div> </div> <!-- 附件列表 --> <div class="attachments-section" style="max-width:800px; margin:0 auto;"> <h4>附件</h4> <ul style="list-style:none; padding-left:0;"> ${allAttachments.filter(att => !att.isEmbedded).map(att => ` <li style="margin:5px 0;"> <a href="data:${att.mimeType};base64,${btoa(String.fromCharCode(...new Uint8Array(att.content)))}" download="${att.fileName}"> 📎 ${att.fileName} </a> </li> `).join('')} </ul> </div>
如果是后端解析,直接把处理好的HTML和附件数据返回给前端渲染;如果是前端解析,就在页面里动态生成DOM即可。
关键注意事项
- 权限问题:确保你的应用有SharePoint文件的读取权限,若要上传图片还需写入权限。
- 编码兼容:部分老版本的MSG/OFT可能用非UTF-8编码,若遇到乱码,可以尝试指定解析编码。
- 大文件处理:后端解析大文件时建议用流式处理,避免内存溢出;前端尽量避免解析超过10MB的文件。
- 跨域问题:前端直接调用SharePoint API时,需确保站点配置了允许跨域的CORS策略,或用SPFx开发绕过跨域限制。
内容的提问来源于stack exchange,提问作者psvs
相关产品推荐
相关产品推荐

