使用Microsoft Graph API批量上传文件至OneDrive后内容无法打开求助
问题诊断与修复方案
核心问题:文件内容上传格式错误
你当前的代码把文件二进制编码为Base64后,用JSON对象{contentBytes: "..."}包裹发送,但Microsoft Graph API的/content端点要求直接发送原始二进制数据,不需要JSON包装。这种错误格式导致文件内容被解析为JSON文本而非原始文件数据,所以文件能创建但无法正常打开。
其他逻辑问题
- 批次大小管理混乱:初始定义
batchSize=20,但循环中又执行batchSize++,导致批次计数逻辑完全错误,可能出现提前或延迟发送批次的情况。 - 文件流读取不完整:
fileStream.Read()不能保证一次性读取所有字节,存在丢失部分文件内容的风险。 - 请求构建冗余:通过
.Content.Request().GetHttpRequestMessage()获取请求后修改方法和内容,不如直接构建PUT请求更简洁。
修正后的代码实现
public async Task BatchUploadFileAsync(string DriveID, GetAllFilesToUpload filesToUpload) { const int batchSize = 20; // 固定批次大小,避免变量复用混乱 var batchesOfFiles = new List<List<FileDatatoUpload>>(); var currentBatch = new List<FileDatatoUpload>(); // 先按批次分组文件 foreach (var file in filesToUpload.Files) { currentBatch.Add(new FileDatatoUpload { FormFile = file.FormFile, Folder = file.Folder, TypeOfDocument = file.TypeOfDocument, SchoolYear = file.SchoolYear, Curriculum = file.Curriculum, Language = file.Language, Semestre = file.Semestre, PathStudent = file.PathStudent, AcademicYear = file.AcademicYear, Student = file.Student }); if (currentBatch.Count == batchSize) { batchesOfFiles.Add(currentBatch); currentBatch = new List<FileDatatoUpload>(); } } if (currentBatch.Count > 0) { batchesOfFiles.Add(currentBatch); } try { foreach (var batchFiles in batchesOfFiles) { var batchRequestContent = new BatchRequestContent(); foreach (var file in batchFiles) { // 确保完整读取文件流 using (var memoryStream = new MemoryStream()) { await file.FormFile.CopyToAsync(memoryStream); memoryStream.Position = 0; // 重置流位置到起始点 // 直接用文件流作为请求内容,无需JSON包装 var streamContent = new StreamContent(memoryStream); // 设置正确的Content-Type,若无法获取可设为application/octet-stream streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(file.FormFile.ContentType); // 构建PUT请求上传文件内容 var requestUrl = _graphServiceClientApp.Users["userId"].Drive.Root .ItemWithPath(Path.Combine(file.PathStudent)) .Content.Request().RequestUrl; var request = new HttpRequestMessage(HttpMethod.Put, requestUrl) { Content = streamContent }; // 添加到批次请求 batchRequestContent.AddBatchRequestStep(request); } } // 发送当前批次 await _graphServiceClientApp.Batch.Request().PostAsync(batchRequestContent); } } catch (ServiceException ex) { Console.WriteLine($"Error uploading: {ex.ToString()}"); } }
关键修正点说明
- 直接发送二进制流:使用
StreamContent包装文件流作为请求内容,完全符合Graph API的要求。 - 修复批次逻辑:用常量定义批次大小,每个批次单独创建
BatchRequestContent,避免交叉污染。 - 可靠读取文件流:使用
CopyToAsync将上传文件复制到MemoryStream,确保完整读取所有内容。 - 正确设置Content-Type:保留原文件的MIME类型,帮助Graph API正确识别文件类型。
内容的提问来源于stack exchange,提问作者Megane Niama
相关产品推荐
相关产品推荐

