【C#】使用HttpClient上传文件到网站服务器和解决出错问题
创始人
2025-01-17 04:36:33
0

第一次使用HttpClient上传文件到网站服务器时,尤其是如果长时间未进行操作,使用Https加密传输协议可能会遇到一些错误。针对这些潜在的问题,以下是一些解决方案,以帮助您顺利上传文件。

文章目录

  • 选择文件
  • 上传文件
    • ContentType
      • multipart/form-data
      • application/octet-stream
    • 报错问题
      • 无法访问对象
      • 未同步执行异常
      • 建立安全通道
  • 接收文件
    • .Net Aspx

选择文件

例如,点击上传文件按钮,通过打开文件对话框来选择文件, 代码如下

var dialog = new Microsoft.Win32.OpenFileDialog(); dialog.Title = "选择上传的文件"; dialog.CheckFileExists = true; dialog.Filter = "*.zip(压缩文件)|*.zip"; dialog.Multiselect = false; if (dialog.ShowDialog() == true) {     DoUploadFileAsync(dialog.FileName).ContinueWith(res => {         Debug.WriteLine($"responseText: {res.Result}");     }); } 

接下来实现上传文件的异步方法DoUploadFileAsync,输出返回响应的结果res.Result

上传文件

实现异步方法DoUploadFileAsync,使用HttpClient上传文件, 代码如下

internal async Task DoUploadFileAsync(string filePath) {     try     {         var url = API_BASE_URL + "/Default.aspx?type=uploadfile"; 		//System.Net.ServicePointManager.Expect100Continue = true;         //System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls;         using (var client = new HttpClient())         {             //client.Timeout = TimeSpan.FromSeconds(10);             //client.DefaultRequestHeaders.Add("Referer", API_BASE_URL + "/"); 			using (var formData = new MultipartFormDataContent()) 			{ 			    using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) 			    { 			        var fileName = System.IO.Path.GetFileName(filePath); 			        using (var streamContent = new StreamContent(fileStream, (int)fileStream.Length)) 			        { 			            //上传文件处理方式省略... 			 			            using (var response = await client.PostAsync(url, formData)) 			            { 			                if (response.IsSuccessStatusCode) 			                { 			                    return await response.Content.ReadAsStringAsync(); 			                } 			                else 			                { 			                    throw new Exception(">>> DoUploadFileAsync NoSuccessStatusCode"); 			                } 			            } 			        } 			    } 			}         }     }     catch(Exception ex)     {         Debug.WriteLine($">>>> DoUploadFileAsync Error:{ex.Message} \nStackTrace:{ex.StackTrace}");//发生一个或多个错误。     }     return string.Empty; } 

上传地址若是加密传输https协议, 就要设置 System.Net.ServicePointManager.SecurityProtocol 使用安全证书

ContentType

在上传文件处理方式中,使用不同的文件内容类型,

multipart/form-data

当使用内容类型为"multipart/form-data",代码如下

var fileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result); fileContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/form-data"); formData.Add(fileContent, "file", fileName);  // 如果需要添加其他表单字段,可以继续添加,注意key与value对应 // form.Add(new StringContent("value"), "key"); 

上传文件时,后台服务器可能响应错误消息,提示路径包含非法字符,

大致可能是文件名有包含中文时乱码引起的,因此以上方法不适用,

application/octet-stream

当使用内容类型为application/octet-stream,改成如下

streamContent.Headers.Add("Content-Type", "application/octet-stream"); var bytes = Encoding.UTF8.GetBytes($"form-data; name=\"file\"; filename=\"{fileName}\"");  var headerValue = ; foreach (var b in bytes) headerValue += (Char)b; streamContent.Headers.Add("Content-Disposition", headerValue);  formData.Add(streamContent, "file", fileName); 

以上方法,可防止中文的文件名乱码

报错问题

关于上传出现报错的问题收集

无法访问对象

报错:无法访问已释放的对象。

看对象名是什么,可能是“System.Net.Http.MultipartFormDataContent”,

这是因为在调用异步时,又调用了一次,调用之前就已自动释放了被引用的对象,

适当使用using () {} 可管理对象在不用时被释放

未同步执行异常

报错:System.Threading.Tasks.Task 1.GetResultCore(Boolean waitCompletionNotification)

可能是执行以下同步代码造成的,

var responseText = client.PostAsync(url, formData).GetAwaiter().GetResult().Content.ReadAsStringAsync().Result; 

试试改成asyncawait调用方式,保证同步执行

建立安全通道

报错:基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。

当请求地址API_BASE_URL是带https协议,那可能会报错安全通道信任问题的异常,

在新建的HttpClientHandler实例设置一个事件,信任所有证书

var hander = new HttpClientHandler(); hander.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => {     // 在这里添加你的证书验证逻辑     // 返回true来表示允许所有证书(不推荐用于生产环境)     return true; }; 

用于生产环境这会不安全,要改使用 System.Net.ServicePointManager.SecurityProtocol,

可能还会报错, 就试试改成如下代码

var hander = new HttpClientHandler(); hander.AllowAutoRedirect = true; hander.UseCookies = true; hander.CookieContainer = cookies; hander.ClientCertificateOptions = ClientCertificateOption.Automatic; 

通过设置ClientCertificateOptions 使用安全认证…

最后,将hander传给client即可

var client = new HttpClient(hander); //... 

接收文件

如果还没有实现接收文件, 这里就在本地服务器上实现一下, 方便测试

后台服务器的开发语言种类繁多, 这里使用一种开发语言C#,

写一个例子, 实现接收文件

.Net Aspx

例如,在Default.aspx页面里实现上传文件,再到后台处理请求接收文件,

上传文件页面内容如下,

上传文件



这里使用怀旧主流的前端框架jQuery, 它的网上免费学习文档丰富

在后台的处理接收文件,调用方法UploadFile(),代码如下

private string UploadFile() {     if (Request.Files.Count > 0)     {         var file = Request.Files[0];         var fileName = System.IO.Path.GetFileName(file.FileName);         var path = System.IO.Path.Combine(Server.MapPath("~/Uploads/"), fileName);         file.SaveAs(path);         return "ok";     }     return "fail"; } 

写到这里为止,期待下次再见!

在这里插入图片描述

相关内容

热门资讯

目前!聚友棋牌辅助透视挂,掌乐... 目前!聚友棋牌辅助透视挂,掌乐麻将确实有挂,真是有挂方针一、聚友棋牌游戏安装教程牌型概率发牌机制”必...
相较于以往!彩虹辅助透视挂,同... 相较于以往!彩虹辅助透视挂,同仁棋牌是有挂,一贯确实有挂同仁棋牌是不是有人用挂微扑克wpk插件教程:...
现就发布提示!腾跃辅助透视挂,... 现就发布提示!腾跃辅助透视挂,雀跃存在有挂,其实有挂工具1、进入游戏-大厅左侧-新手福利-激活码辅助...
据统计!金牛大厅辅助透视挂,哥... 据统计!金牛大厅辅助透视挂,哥哥打大a真的有挂,其实证实有挂1、金牛大厅辅助器安装包、金牛大厅辅助器...
插件辅助挂!钢铁侠辅助透视挂,... 插件辅助挂!钢铁侠辅助透视挂,飞飞黄梅棋牌是有挂,果然有挂细节黄梅棋牌脚本下载中分为三种模型:黄梅棋...
更值得关注的是!决胜奕福辅助透... 更值得关注的是!决胜奕福辅助透视挂,家家乐牌吧确实有挂,一贯详细教程1、首先打开家家乐牌吧辅助器下载...
2026版教学!518互娱辅助... 2026版教学!518互娱辅助透视挂,小南四川长牌是真的有挂,竟然有挂秘诀1、进入到小南四川长牌是否...
网友热议!掌上风云辅助透视挂,... 网友热议!掌上风云辅助透视挂,指尖四川麻将真的有挂,一直有挂方略1、四川麻将辅助软件下载优化,四川麻...
近年来!唯思竞技麻将辅助透视挂... 近年来!唯思竞技麻将辅助透视挂,正宗钟祥麻将真的是有挂,竟然有挂攻略1、唯思竞技麻将模拟器是什么优化...
截至发稿!涡阳茶馆辅助透视挂,... 截至发稿!涡阳茶馆辅助透视挂,小南四川长牌是真的有挂,一直的确有挂运小南四川长牌辅助工具,进入游戏界...