C#.NET RESTful服务发送大附件时出现500错误求助
解决大附件(>3MB)通过Web服务发送邮件的请求失败问题
我看你遇到的核心问题是:WinForm端把附件转成Byte[]序列化到JSON后调用Web服务,一旦附件超过3MB就会在HttpWebResponse oWebResp = myReq.GetResponse()处报错,即便已经调整了maxAllowedContentLength也无效。这是因为你只配置了IIS层面的限制,ASP.NET本身还有额外的请求大小限制,同时用JSON传输大二进制数据也不是最优方案,咱们一步步来解决:
1. 补全ASP.NET的请求大小限制配置
maxAllowedContentLength是IIS层面的限制,但传统ASP.NET(你的代码基于.NET Framework)还有自身的maxRequestLength限制,必须同时配置才能生效:
在Web.config中添加/修改以下配置:
<system.web> <!-- 单位为KB,这里设置为50MB,executionTimeout延长超时时间避免传输中断 --> <httpRuntime maxRequestLength="51200" executionTimeout="300" /> </system.web> <system.webServer> <security> <requestFiltering> <!-- 单位为Bytes,这里设置为50MB,和上面的maxRequestLength数值匹配 --> <requestLimits maxAllowedContentLength="52428800" /> </requestFiltering> </security> </system.webServer>
2. 优化大二进制数据的传输方式(推荐方案)
把Byte[]序列化为JSON的效率极低,还容易触发各种大小限制,更合理的方式是用multipart/form-data分块上传文件,避免把二进制数据塞进JSON里:
修改WinForm端代码,改用multipart/form-data上传
public void SendEmail(String sender, String recipient, String subject, String htmlBody, String fileLocation, String AttachemntNewName) { string apiUrl = "http://ADDRESS_TO_SERVER/Home/SendMail"; HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(apiUrl); myReq.Method = "POST"; // 定义multipart分隔符 string boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW"; myReq.ContentType = $"multipart/form-data; boundary={boundary}"; myReq.Timeout = 60000; // 延长超时时间到60秒 myReq.Credentials = CredentialCache.DefaultCredentials; using (var stream = new MemoryStream()) using (var writer = new StreamWriter(stream)) { // 写入邮件文本字段 writer.WriteLine($"--{boundary}"); writer.WriteLine("Content-Disposition: form-data; name=\"Sender\""); writer.WriteLine(); writer.WriteLine(sender); writer.WriteLine($"--{boundary}"); writer.WriteLine("Content-Disposition: form-data; name=\"Recipient\""); writer.WriteLine(); writer.WriteLine(recipient); writer.WriteLine($"--{boundary}"); writer.WriteLine("Content-Disposition: form-data; name=\"Subject\""); writer.WriteLine(); writer.WriteLine(subject); writer.WriteLine($"--{boundary}"); writer.WriteLine("Content-Disposition: form-data; name=\"HtmlBody\""); writer.WriteLine(); writer.WriteLine(htmlBody); // 处理附件(如果存在) if (!string.IsNullOrEmpty(fileLocation)) { var fileName = string.IsNullOrEmpty(AttachemntNewName) ? Path.GetFileName(fileLocation) : AttachemntNewName; var fileExt = Path.GetExtension(fileName).ToLower(); var mimeType = MimeTypesAutoGet(fileExt); writer.WriteLine($"--{boundary}"); writer.WriteLine($"Content-Disposition: form-data; name=\"FileBinary\"; filename=\"{fileName}\""); writer.WriteLine($"Content-Type: {mimeType}"); writer.WriteLine(); writer.Flush(); // 写入文件二进制数据 using (var fileStream = new FileStream(fileLocation, FileMode.Open)) { fileStream.CopyTo(stream); } writer.WriteLine(); } // 结束分隔符 writer.WriteLine($"--{boundary}--"); writer.Flush(); stream.Position = 0; myReq.ContentLength = stream.Length; using (var reqStream = myReq.GetRequestStream()) { stream.CopyTo(reqStream); } try { using (HttpWebResponse oWebResp = myReq.GetResponse() as HttpWebResponse) { // 可在此处添加响应状态检查逻辑 } } catch (WebException Ex) { MessageBox.Show(Ex.ToString()); } } }
修改Web服务控制器,接收multipart/form-data请求
public class HomeController : Controller { private IMailer _mailer = new Mailer(); public ActionResult Index() { return View(); } [HttpPost] public ActionResult SendMail() { var emailContentDto = new EmailContentDto { Sender = Request.Form["Sender"], Recipient = Request.Form["Recipient"], Subject = Request.Form["Subject"], HtmlBody = Request.Form["HtmlBody"] }; // 处理上传的附件 if (Request.Files.Count > 0) { var uploadedFile = Request.Files[0]; if (uploadedFile.ContentLength > 0) { using (var ms = new MemoryStream()) { uploadedFile.InputStream.CopyTo(ms); emailContentDto.FileBinary = ms.ToArray(); emailContentDto.FileName = uploadedFile.FileName; emailContentDto.FileFormat = uploadedFile.ContentType; } } } _mailer.SendMail(emailContentDto); return new HttpStatusCodeResult(HttpStatusCode.OK); } }
3. 其他需要注意的细节
- 延长
SmtpClient的超时时间:你当前设置的80秒对于大附件发送可能不够,可以调整到120秒以上 - 确保Web服务所在服务器有足够的内存和临时磁盘空间,用于处理大文件上传
- WinForm端的
HttpWebRequest超时时间要和文件大小匹配,避免传输中途超时
内容的提问来源于stack exchange,提问作者Ashley Miller
相关产品推荐
相关产品推荐

