You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript开发的Outlook插件中使用MSGraphClient上传附件至SharePoint

问题根因

  • 你引入的MSGraphClient来自@microsoft/sp-http包,这个类是仅用于SharePoint Framework(SPFx)项目的专属类,你开发的是Outlook外接程序,运行环境不支持这个类,所以必然返回未定义
  • 你在saveAttachment函数中只声明了graphClient变量,没有做任何初始化操作,调用时当然是undefined状态

解决方案

直接用你已经引入的@microsoft/microsoft-graph-client包的Client类,搭配SSO拿到的访问令牌初始化即可,步骤如下:

1. 补充安装依赖(如果未安装)

npm install @microsoft/microsoft-graph-client

2. 修正代码逻辑

你之前调用的getGraphData已经通过SSO拿到了Graph访问令牌,直接复用令牌初始化Graph客户端即可,如果你的ssoauthhelper中的getGraphData没有返回访问令牌,修改该方法直接返回拿到的access_token即可,修正后的完整代码如下:

/*
 * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
 * See LICENSE in the project root for license information.
 */

// images references in the manifest
import "../../assets/icon-16.png";
import "../../assets/icon-32.png";
import "../../assets/icon-80.png";

/* global $, document, Office */
// 删掉无用的MSGraphClient引入
import { Client } from "@microsoft/microsoft-graph-client";
import { getGraphData } from "./../helpers/ssoauthhelper";

// 全局存储Graph客户端实例
let graphClient: Client;

Office.onReady((info) => {
  if (info.host === Office.HostType.Outlook) {
    $(function () {
      // 初始化时拿到SSO令牌,直接初始化Graph客户端
      getGraphData().then(token => {
        graphClient = Client.initWithMiddleware({
          authProvider: {
            getAccessToken: async () => token
          }
        });
      });
      
      $("#saveAttachments").on("click", async function() {
        const checkedAttachments = $(".atchCheckBoxes > input[type=checkbox]:checked");
        for (const checkbox of checkedAttachments) {
          const attachmentId = $(checkbox).val();
          const attachment = Office.context.mailbox.item.attachments.find(a => a.id === attachmentId);
          if (!attachment) continue;
          
          Office.context.mailbox.item.getAttachmentContentAsync(attachment.id, async (asyncResult) => {
            if (asyncResult.status === Office.AsyncResultStatus.Succeeded) {
              // base64内容转Uint8Array,避免上传后文件损坏
              const byteCharacters = atob(asyncResult.value.content);
              const byteNumbers = new Array(byteCharacters.length);
              for (let i = 0; i < byteCharacters.length; i++) {
                byteNumbers[i] = byteCharacters.charCodeAt(i);
              }
              const contentBuffer = new Uint8Array(byteNumbers);
              await saveAttachment(contentBuffer, attachment.name);
            }
          });
        }
      });
    });
  }
});

async function saveAttachment(content: Uint8Array, fileName: string): Promise<string> {
  // 替换为你实际的SharePoint站点ID和目标文档库ID
  const siteId = "你的SharePoint站点ID";
  const driveId = "目标文档库ID";
  // SharePoint文档库上传API路径
  const uploadApi = `/sites/${siteId}/drives/${driveId}/root:/${fileName}:/content`;
  
  // 小于4MB的文件直接上传
  const saveResult = await graphClient.api(uploadApi).put(content);
  console.log(`Save Attachment result for ${fileName}: `, saveResult);
  return saveResult.id;
}

3. 配置注意事项

  • 先确认你的Outlook插件manifest中已经正确配置了SSO,并且申请了上传需要的Graph权限,比如Files.ReadWrite.All、Sites.ReadWrite.All
  • 附件大小超过4MB时,需要用Graph的分片上传接口createUploadSession处理,不能直接用put方法上传
  • 如果不需要固定传到指定SharePoint文档库,也可以直接用用户OneDrive的路径/me/drive/root:/${fileName}:/content上传

内容的提问来源于stack exchange,提问作者Umair Aslam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:45:03