ASP.NET C#中WebClient上传大文件遇413错误求助
解决大文件上传413错误的方案
一、先明确核心问题:目标服务器的限制
你遇到的413 Request Entity Too Large是远程病毒检测站点返回的错误,说明对方服务器限制了单次请求的大小,而非你本地ASP.NET站点的配置问题。优先要做的是:
- 查阅该病毒检测API的官方文档,确认其允许的最大上传文件尺寸
- 若API不支持50MB以上文件,确认是否提供分块上传的接口
二、使用WebClient实现大文件上传的可行方案
WebClient默认的UploadFile方法会把整个文件加载到内存后一次性发送,既容易引发内存问题,也无法绕过目标服务器的单次请求大小限制。如果目标API支持分块上传,可以手动扩展WebClient实现分块上传:
public string UploadLargeFileInChunks(string filePath, string uploadUrl, int chunkSize = 1024 * 1024 * 5) // 按5MB每块分割 { using (var client = new MyWebClient()) { client.QueryString.Add("key", APIKey); client.Headers.Add("Content-type", "binary/octet-stream"); ServicePointManager.SecurityProtocol = (SecurityProtocolType)768 | (SecurityProtocolType)3072; using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { long totalBytes = fileStream.Length; long bytesSent = 0; byte[] buffer = new byte[chunkSize]; int bytesRead; while ((bytesRead = fileStream.Read(buffer, 0, chunkSize)) > 0) { // 根据目标API的分块规则设置请求头,比如Content-Range client.Headers.Add("Content-Range", $"bytes {bytesSent}-{bytesSent + bytesRead - 1}/{totalBytes}"); byte[] response = client.UploadData(uploadUrl, "PUT", buffer.Take(bytesRead).ToArray()); // 解析分块响应,确认上传状态 string json = Encoding.Default.GetString(response); var result = ParseJSON(json); if (!result.ContainsKey("success")) { throw new Exception(result["result"]); } bytesSent += bytesRead; } // 若API要求上传完成后触发合并操作,发送合并请求 var finalResponse = client.UploadString($"{uploadUrl}/finish", "POST", "{\"scan_id\":\"temp_id\"}"); var finalResult = ParseJSON(finalResponse); return finalResult["scan_id"]; } } }
注:上述代码需根据目标API的分块协议调整请求头和合并逻辑,不同站点的规则可能存在差异。
三、ASP.NET Web Forms中其他大文件上传方法
1. 使用HttpWebRequest手动控制上传
相比WebClient,HttpWebRequest提供更精细的控制,支持分块流式上传,无需将整个文件加载到内存:
public string UploadLargeFileWithHttpWebRequest(string filePath, string uploadUrl) { var request = (HttpWebRequest)WebRequest.Create(uploadUrl); request.Method = "POST"; request.ContentType = "binary/octet-stream"; request.Headers.Add("key", APIKey); request.ServicePoint.SecurityProtocol = (SecurityProtocolType)768 | (SecurityProtocolType)3072; request.SendChunked = true; // 启用分块发送 using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) using (var requestStream = request.GetRequestStream()) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0) { requestStream.Write(buffer, 0, bytesRead); requestStream.Flush(); } } using (var response = (HttpWebResponse)request.GetResponse()) using (var responseStream = response.GetResponseStream()) using (var reader = new StreamReader(responseStream)) { string json = reader.ReadToEnd(); var result = ParseJSON(json); if (result.ContainsKey("scan_id")) { return result["scan_id"]; } throw new Exception(result["result"]); } }
2. 前端分块+后端合并
如果目标服务器不支持分块,可以先在前端将文件分块,上传到你的ASP.NET站点合并后,再转发给病毒检测API:
- 前端用JavaScript的
File.slice()方法分割文件,逐个发送到后端接口 - 后端(ASP.NET Web Forms)接收每个分块并保存到临时目录,所有分块上传完成后合并为完整文件,再调用病毒检测API
3. 完善本地IIS的上传限制配置
如果你调整maxAllowedContentLength和maxRequestLength后仍有问题,需检查:
- 确认web.config配置是否正确:
<system.web> <httpRuntime maxRequestLength="2147483" executionTimeout="3600" /> <!-- 单位KB,对应2GB --> </system.web> <system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="2147483648" /> <!-- 单位字节,对应2GB --> </requestFiltering> </security> </system.webServer> - 若使用IIS Express,需修改
applicationhost.config文件(通常在Documents\IISExpress\config目录)中的对应设置,避免覆盖web.config的配置 - 检查IIS站点的「请求筛选」功能,是否单独设置了请求大小限制
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

