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

使用Graph Api上传大文件到ToDoTask时出现AccessToken为空错误

问题解答

1. 是否允许使用LargeFileUploadTask上传大文件到ToDoTask?

是的,Graph API支持通过LargeFileUploadTask为ToDo任务上传大文件附件。你遇到的错误并非因为不支持该方式,而是初始化LargeFileUploadTask时缺少了关键的认证依赖。

2. 错误原因分析

你当前初始化LargeFileUploadTask的代码只传入了上传会话、文件流和分块大小,但没有传入Graph服务客户端的请求适配器(RequestAdapter)。虽然上传URL本身不需要携带Auth头,但LargeFileUploadTask内部处理分块上传、重试等逻辑时,需要依赖请求适配器获取有效认证令牌,缺少该参数会导致请求时令牌为空,触发InvalidAuthenticationToken错误。

3. 正确实现方式

修改LargeFileUploadTask的初始化代码,补充传入_graphServiceClient.RequestAdapter参数。同时确保你的应用已申请正确的权限(如Tasks.ReadWrite或Tasks.ReadWrite.All)。

修正后的核心代码片段

using (var _stream = new MemoryStream(_attachment.ContentBytes))
{
    _stream.Position = 0;
    // 补充传入RequestAdapter参数
    LargeFileUploadTask<TaskFileAttachment> _largeFileUploadTask = 
        new LargeFileUploadTask<TaskFileAttachment>(_uploadSession, _graphServiceClient.RequestAdapter, _stream, MaxChunkSize);
    try
    {
        await _largeFileUploadTask.UploadAsync();
    }
    catch (ServiceException errorGraph)
    {
        if (errorGraph.StatusCode is HttpStatusCode.InternalServerError or HttpStatusCode.BadGateway
            or HttpStatusCode.ServiceUnavailable or HttpStatusCode.GatewayTimeout)
        {
            await Task.Delay(1000); // 用Task.Delay替代Thread.Sleep,符合异步编程规范
            await _largeFileUploadTask.ResumeAsync();
        }
        else
            throw;
    }
}

完整修正后的方法代码

public async Task CreateTaskBigAttachments(string idList, string title, List<string> categories,
    BodyType contentType, string content, Importance importance, bool isRemindOn, DateTime? dueTime, cAttachment[] attachments = null)
{
    try
    {
        var _newTask = new TodoTask
        {
            Title = title,
            Categories = categories,
            Body = new ItemBody()
            {
                ContentType = contentType,
                Content = content,
            },
            IsReminderOn = isRemindOn,
            Importance = importance
        };
        if (dueTime.HasValue)
        {
            var _timeZone = TimeZoneInfo.Local;
            _newTask.DueDateTime = DateTimeTimeZone.FromDateTime(dueTime.Value, _timeZone.StandardName);
        }
        var _task = await _graphServiceClient.Me.Todo.Lists[idList].Tasks.Request().AddAsync(_newTask);
        
        if (attachments != null && attachments.Length > 0)
        {
            foreach (var _attachment in attachments)
            {
                var _attachmentContentSize = _attachment.ContentBytes.Length;
                var _attachmentInfo = new AttachmentInfo
                {
                    AttachmentType = AttachmentType.File,
                    Name = _attachment.FileName,
                    Size = _attachmentContentSize,
                    ContentType = _attachment.ContentType
                };
                var _uploadSession = await _graphServiceClient.Me
                    .Todo.Lists[idList].Tasks[_task.Id]
                    .Attachments.CreateUploadSession(_attachmentInfo).Request().PostAsync();
                
                using (var _stream = new MemoryStream(_attachment.ContentBytes))
                {
                    _stream.Position = 0;
                    // 关键修正:传入RequestAdapter
                    LargeFileUploadTask<TaskFileAttachment> _largeFileUploadTask = 
                        new LargeFileUploadTask<TaskFileAttachment>(_uploadSession, _graphServiceClient.RequestAdapter, _stream, MaxChunkSize);
                    try
                    {
                        await _largeFileUploadTask.UploadAsync();
                    }
                    catch (ServiceException errorGraph)
                    {
                        if (errorGraph.StatusCode is HttpStatusCode.InternalServerError or HttpStatusCode.BadGateway
                            or HttpStatusCode.ServiceUnavailable or HttpStatusCode.GatewayTimeout)
                        {
                            await Task.Delay(1000);
                            await _largeFileUploadTask.ResumeAsync();
                        }
                        else
                            throw;
                    }
                }
            }
        }
    }
    catch (ServiceException errorGraph)
    {
        throw;
    }
    catch (Exception ex)
    {
        throw;
    }
}

额外优化建议

  • 用Task.Delay(1000)替代Thread.Sleep(1000),避免阻塞线程,更符合异步编程最佳实践。
  • 合并attachments != null和attachments.Length > 0的判断,简化代码逻辑。

内容的提问来源于stack exchange,提问作者Salvador Ruiz Guevara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:35:51