C#使用Microsoft.Graph上传文件到SharePoint后如何对比本地与云端文件哈希
问题根因
你遇到的403报错原因是System.Net.WebClient没有携带你通过Microsoft Graph API认证得到的授权令牌,直接请求SharePoint的文件资源地址会被权限校验拦截。另外无需手动下载文件计算哈希,Microsoft Graph返回的DriveItem资源本身就包含官方预计算的哈希值,直接调用即可,性能更高。
正确实现步骤
1. 确认AAD应用权限
先确保你注册的AAD应用已经授予了对应SharePoint站点的以下应用权限/委托权限(根据你的应用身份选择),并完成管理员同意:
Files.Read.All或Sites.Read.All(仅读取文件元数据的最小权限)- 如果是上传后立即校验,你已有的上传权限(
Files.ReadWrite.All/Sites.ReadWrite.All)已经足够,无需额外加权限
2. 调用Graph API获取云端文件哈希
文件上传成功后,Graph会返回对应DriveItem对象,直接取file.hashes属性即可,里面包含sha1Hash、sha256Hash、quickXorHash三种预计算的哈希值,官方推荐用quickXorHash做文件一致性校验,性能最优。
示例代码:
// 假设你已经初始化了GraphServiceClient实例,命名为graphClient // 上传文件的代码执行后拿到driveItem对象,或者根据文件ID/路径查询 var driveItem = await graphClient .Sites["你的SharePoint站点ID"] .Drive .Root .ItemWithPath("文件在SharePoint中的相对路径") .Request() .Select("file,id,name") // 只请求需要的元数据,减少响应体积 .GetAsync(); // 取出云端的quickXorHash值 string cloudHash = driveItem.File.Hashes.QuickXorHash;
3. 本地计算相同算法的哈希做对比
因为Graph返回的是QuickXorHash,你需要在本地用相同算法计算本地文件的哈希值,和云端返回的对比即可:
// 本地计算QuickXorHash的实现,适配.NET Framework 4.6.1 public static string ComputeQuickXorHash(string filePath) { const int shift = 11; const int width = 160; ulong[] data = new ulong[(width + 63) / 64]; int length = 0; using (var stream = File.OpenRead(filePath)) { int shiftSoFar = 0; byte[] buffer = new byte[1024 * 1024]; int bytesRead; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) { length += bytesRead; for (int i = 0; i < bytesRead; i++) { int byteIndex = shiftSoFar / 8; int bitShift = shiftSoFar % 8; ulong val = buffer[i]; data[byteIndex % (data.Length)] ^= val << bitShift; if (bitShift > 64 - 8) { data[(byteIndex + 1) % data.Length] ^= val >> (64 - bitShift); } shiftSoFar = (shiftSoFar + shift) % width; } } } // 把长度信息也异或进去 byte[] lengthBytes = BitConverter.GetBytes(length); for (int i = 0; i < lengthBytes.Length; i++) { data[i % data.Length] ^= (ulong)lengthBytes[i] << (8 * i); } // 转base64字符串,和Graph返回的格式一致 byte[] hashBytes = new byte[data.Length * 8]; for (int i = 0; i < data.Length; i++) { Buffer.BlockCopy(BitConverter.GetBytes(data[i]), 0, hashBytes, i * 8, 8); } return Convert.ToBase64String(hashBytes).TrimEnd('='); }
4. 校验逻辑
直接对比本地计算的哈希和云端返回的哈希即可:
string localHash = ComputeQuickXorHash(@"本地文件路径"); if (localHash.Equals(cloudHash, StringComparison.Ordinal)) { // 文件上传一致,校验通过 } else { // 文件损坏,需要重新上传 }
可选方案:用MD5校验
如果你一定要用MD5做校验,不要用WebClient单独下载文件,而是通过Graph SDK的Content接口下载文件流,SDK会自动携带授权令牌,不会出现403报错:
using (var stream = await graphClient.Sites["站点ID"].Drive.Root.ItemWithPath("文件路径").Content.Request().GetAsync()) using (var md5 = MD5.Create()) { var hash = md5.ComputeHash(stream); string cloudMd5 = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); }
内容的提问来源于stack exchange,提问作者Ajit Choubey
相关产品推荐
相关产品推荐

