C# UWP使用HttpClient发带Range、Content-Length的PUT请求上传图片报Invalid Range
核心错误原因
- 前两次尝试使用
MultipartFormDataContent构造表单格式请求,与curl示例的请求结构完全不符:curl是直接把图片二进制数据作为整个请求体发送,没有任何表单字段包装,服务器不会解析表单结构因此直接报错。 - 第三次尝试混淆了请求头
Range和内容头Content-Range:curl发送的是请求头Range: bytes=0-99999,但你给StreamContent加的是内容头Content-Range,服务器没有收到预期的Range请求头,因此返回Invalid Range。 - UWP存在沙箱文件访问限制,直接通过文件路径调用
File.OpenRead读取非应用沙箱内的文件会触发权限异常,需使用UWP原生的StorageFileAPI访问文件。
UWP环境可运行实现方案
using System; using System.Net.Http; using System.Net.Http.Headers; using System.Diagnostics; using Windows.Storage; using System.IO; // 建议将HttpClient声明为单例,不要每次请求新建,避免端口占用问题 private static readonly HttpClient _httpClient = new HttpClient(); /// <summary> /// UWP环境上传图片实现 /// </summary> /// <param name="targetUrl">上传目标地址</param> /// <param name="imageFile">通过FileOpenPicker/StorageFolder获取的图片文件对象</param> /// <returns>是否上传成功</returns> public static async Task<bool> UploadImageAsync(string targetUrl, StorageFile imageFile) { try { // 读取文件大小 var fileProperties = await imageFile.GetBasicPropertiesAsync(); long fileSize = fileProperties.Size; string rangeHeaderValue = $"bytes=0-{fileSize - 1}"; // 构造请求消息 using var request = new HttpRequestMessage(HttpMethod.Put, targetUrl); // 添加请求头Range request.Headers.TryAddWithoutValidation("Range", rangeHeaderValue); // 打开文件流 using var fileStream = await imageFile.OpenStreamForReadAsync(); using var content = new StreamContent(fileStream); // 设置内容头 content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); content.Headers.ContentLength = fileSize; // 关联请求内容 request.Content = content; // 发送请求 using var response = await _httpClient.SendAsync(request); // 可选:校验响应状态码 response.EnsureSuccessStatusCode(); var responseContent = await response.Content.ReadAsStringAsync(); Debug.WriteLine($"上传响应:{responseContent}"); return true; } catch (Exception ex) { Debug.WriteLine($"上传失败:{ex.ToString()}"); return false; } }
注意事项
- 必须在UWP项目的Package.appxmanifest中开启
Internet(客户端)权限,否则无法发起网络请求。 - 如果需要访问系统图片库的文件,需要额外在manifest中开启
图片库权限;如果通过FileOpenPicker让用户主动选择文件,无需额外权限即可获取StorageFile对象。 - HttpClient建议全局单例复用,避免频繁创建销毁实例导致的端口耗尽问题。
内容的提问来源于stack exchange,提问作者Imam Mohammad Bokhary
相关产品推荐
相关产品推荐

