流式上传文件至MVC控制器时无法捕获HttpWebRequest异常
如何让后端API的异常传递到前端Upload控制器?
首先得把问题点透:你的Upload方法只完成了文件流的发送,但完全没处理API返回的响应。HttpWebRequest这个类有点“被动”——哪怕后端返回了500错误,只要你不主动去获取响应、检查状态码,它就不会触发任何异常,你的代码自然感知不到后端保存失败了。
接下来给你具体的修改方案,分几步来:
1. 必须读取并校验API响应
在写完请求流之后,一定要调用GetResponse()获取后端的响应,然后检查Http状态码。如果状态码是错误类型(比如500),就手动抛出异常,这样Upload方法的catch块就能捕获到。
2. 用using语句管理资源(替代手动Close/Dispose)
手动调用Close和Dispose很容易遗漏,用using语句可以自动释放流和请求/响应资源,代码更简洁也更安全。
3. 修正catch块的字符串格式化错误
你原来的代码里String.Format少传了参数,会导致格式化失败,这个小问题也一起改掉。
修改后的Upload方法代码:
public ActionResult Upload() { try { HttpPostedFileBase file = Request.Files[0]; using (Stream fileStream = file.InputStream) { string url = ConfigurationManager.AppSettings[ConfigurationParams.ServiceGatewayURI]; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.Method = "POST"; request.AllowWriteStreamBuffering = false; request.Timeout = 86400000; request.ContentType = "application/json"; // 这里注意:如果是上传文件,Content-Type是否应该用multipart/form-data?暂时保留你原有的逻辑设置 request.ContentLength = fileStream.Length; using (Stream outputStream = request.GetRequestStream()) { int byteLength = 1024; byte[] chunk = new byte[byteLength]; while (fileStream.Position < fileStream.Length) { int len = fileStream.Read(chunk, 0, byteLength); outputStream.Write(chunk, 0, len); } } // 关键步骤:获取并校验响应 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { // 检查状态码,如果不是成功状态,抛出异常 if (response.StatusCode != HttpStatusCode.OK) { throw new Exception($"API返回错误状态码:{(int)response.StatusCode} - {response.StatusDescription}"); } // 如果需要读取API返回的具体内容,可以在这里处理 using (StreamReader reader = new StreamReader(response.GetResponseStream())) { string responseContent = reader.ReadToEnd(); // 可根据实际需求对响应内容做进一步处理 } } return Json("文件上传成功"); } } catch (Exception ex) { return Json(new { error = string.Format("文件上传失败:{0}", ex.Message) }); } }
额外的后端API优化建议
为了确保异常能正确返回500状态码,你可以在API的Post方法里统一处理异常:
public String Post(string documentName) { try { return context.SaveFile(documentName, Request.Content.ReadAsStreamAsync().Result); } catch (Exception ex) { // 先记录异常日志便于排查 // 抛出Http响应异常,返回500状态码 throw new HttpResponseException(HttpStatusCode.InternalServerError); // 或者返回带具体错误信息的响应: // return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message); } }
这样一来,当SaveFile抛出异常时,API会返回明确的500响应,Upload方法在获取响应时检测到状态码错误,就会抛出异常并进入catch块,最终把错误信息返回给前端。
内容的提问来源于stack exchange,提问作者Meeple
相关产品推荐
相关产品推荐

