如何在Azure表存储中用System.Net.Http.HttpClient正确设置ContentMD5属性
我帮你排查了问题,发现有两个关键问题需要解决:一个是代码里的请求方法不匹配,另一个是跨平台下HttpClient对Content-MD5头的处理差异。下面是具体的修复方案和解释:
首先,修正请求发送的代码错误
你当前创建了PUT方法的HttpRequestMessage,但完全没用到它,反而调用PostAsync发送了POST请求——这会导致你设置的所有请求配置都失效,包括Content-MD5头。先把这部分代码修正过来:
string contentString = "<some xml content>"; // 统一MD5计算逻辑(确保跨平台一致) System.Security.Cryptography.MD5CryptoServiceProvider csp = new MD5CryptoServiceProvider(); var hash = csp.ComputeHash(Encoding.UTF8.GetBytes(contentString)); var hashString = ByteArrayToString(hash); // 得到和之前一致的十六进制字符串 // 初始化HttpClient和请求消息 System.Net.Http.HttpClient client = new HttpClient(); Uri uri = new Uri("http://woschmi01.table.core.windows.net/Test2018()"); HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Put, uri); var content = new StringContent(contentString); // 添加Content-MD5头到内容头 content.Headers.Add("Content-MD5", hashString); requestMessage.Content = content; // 发送请求 var response = await SendRequest(client, requestMessage); // 修正后的SendRequest方法 async Task<HttpResponseMessage> SendRequest(HttpClient client, HttpRequestMessage requestMessage) { HttpResponseMessage response = await client.SendAsync(requestMessage); return response; } // 确保十六进制字符串格式统一(大写、无连字符) static string ByteArrayToString(byte[] ba) { return BitConverter.ToString(ba).Replace("-", "").ToUpperInvariant(); }
解决iOS上Content-MD5头为空的问题
iOS平台的HttpClient底层依赖NSURLSession,它会自动管理部分标准HTTP头(包括Content-MD5),直接用content.Headers.Add添加的头可能被过滤掉。这里给你两个可行的解决方案:
方案1:自定义消息处理程序(跨平台兼容)
创建一个自定义的消息处理程序,强制保留你添加的Content-MD5头,绕过系统的自动过滤:
public class ContentMd5PreserveHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request.Content != null) { // 检查是否已设置Content-MD5头 var md5Header = request.Content.Headers.FirstOrDefault(h => h.Key.Equals("Content-MD5", StringComparison.OrdinalIgnoreCase)); if (md5Header.Value != null && md5Header.Value.Any()) { // 先移除可能被系统处理的头,再重新添加(强制保留) request.Content.Headers.Remove("Content-MD5"); request.Content.Headers.TryAddWithoutValidation("Content-MD5", md5Header.Value.First()); } } return await base.SendAsync(request, cancellationToken); } } // 初始化HttpClient时使用这个处理程序 var handler = new ContentMd5PreserveHandler(); handler.InnerHandler = new HttpClientHandler(); System.Net.Http.HttpClient client = new HttpClient(handler);
方案2:直接添加到请求头(简化版)
如果自定义处理程序太复杂,可以尝试把Content-MD5头添加到请求的Headers中(虽然严格来说它属于内容头,但Azure表存储通常会接受这种方式):
// 替换原来的content.Headers.Add,改成添加到请求消息的Headers requestMessage.Headers.Add("Content-MD5", hashString);
额外验证:确保哈希值跨平台一致
为了避免MD5计算结果不一致,要注意两个细节:
- 确保
contentString的编码是UTF-8,且没有额外的BOM(字节顺序标记) ByteArrayToString方法要统一返回大写的十六进制字符串(添加.ToUpperInvariant(),避免大小写差异导致认证失败)
这样调整后,UWP和iOS平台的请求都会包含和之前一致的Content-MD5头,Fiddler里能看到正确的值,SharedKey认证也能正常通过。
内容的提问来源于stack exchange,提问作者Roland Schmidt
相关产品推荐
相关产品推荐

