ASP.NET Core Web API中HttpClient发送PDF请求超时问题排查
我使用Visual Studio的ASP.NET Core Web API项目模板创建了一个支持文件上传的Web API,并编写了处理PDF报告上传的控制器动作方法。
控制器动作代码
[HttpPost("Report/{reportId")] public async Task<IActionResult> AttachReport(string reportId) { Reporter client = new Reporter(); await client.AttachReportToRequest(reportId); return }
请求发送方法代码
public async Task<HttpResponseMessage> AttachReportToRequest(string reportId) { try { if (authToken is null) { authToken = await login("username", "passw0rd"); } HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, "/api/to/app/server/reportInfo"); requestMessage.Headers.Authorization = new AuthenticationHeaderValue("app-JWT", authToken); string scanReportFile = $"{Directory.GetCurrentDirectory()}\Reports\sample_report.pdf"; MultipartFormDataContent requestBody = new MultipartFormDataContent(); //Create values JSON payload requestBody.Add(new StringContent($"\"values\":{{ \"ReportId\":\"{reportId}\", \"Description\":\"test\", \"Submitter\":\"John Smith\", \"Number of Attachment\":\"1\" }}"), "entry"); requestBody.Add(new StreamContent(File.OpenRead("C:/Users/myuser/Documents/ReporterApp/myreport.pdf")), "file-attachment", "C:/Users/myuser/Documents/ReporterApp/myreport.pdf"); requestMessage.Content = requestBody; HttpResponseMessage attachmentResponse = await httpClient.SendAsync(requestMessage); return attachmentResponse; } catch (Exception) { throw; } }
每次调用HttpClient.SendAsync发送请求都会超时,无法收到服务器响应,但使用Postman调用同一端点、发送相同的multipart/form-data类型请求却能成功。我尝试将文件流放入using块、更换不同文件类型,都无法解决问题,想知道SendAsync请求超时的具体原因是什么?
1. JSON格式不完整
你手动拼接的entry字段JSON缺少外层大括号,正确结构应为{"values": {...}},而非仅"values": {...}。服务器解析格式错误的JSON时可能陷入阻塞,导致请求超时。
解决方法:
补全JSON结构,或改用序列化工具避免手动拼接错误:
// 方式1:补全JSON外层大括号 requestBody.Add(new StringContent($"{{ \"values\":{{ \"ReportId\":\"{reportId}\", \"Description\":\"test\", \"Submitter\":\"John Smith\", \"Number of Attachment\":\"1\" }} }}"), "entry"); // 方式2:使用JsonSerializer序列化(更可靠) var payload = new { values = new { ReportId = reportId, Description = "test", Submitter = "John Smith", NumberOfAttachment = "1" } }; string json = JsonSerializer.Serialize(payload); requestBody.Add(new StringContent(json, Encoding.UTF8, "application/json"), "entry");
2. 文件参数传递错误
添加文件时,第三个参数传递了完整文件路径,而服务器通常只需要文件名(如myreport.pdf),路径格式可能导致服务器解析异常。
解决方法:
改用Path.GetFileName提取纯文件名:
var filePath = "C:/Users/myuser/Documents/ReporterApp/myreport.pdf"; requestBody.Add(new StreamContent(File.OpenRead(filePath)), "file-attachment", Path.GetFileName(filePath));
3. HttpClient实例管理不当
如果每次调用都新建HttpClient实例,会导致套接字资源耗尽,进而引发超时。Postman因复用连接不会出现此问题。
解决方法:
遵循.NET最佳实践,复用HttpClient实例——比如通过IHttpClientFactory注册为单例,或在应用生命周期内保持同一个实例。
4. 请求内容未指定编码和媒体类型
手动创建的StringContent未指定编码和application/json媒体类型,服务器可能无法正确解析内容,导致处理超时。
解决方法:
创建StringContent时明确指定参数:
new StringContent(json, Encoding.UTF8, "application/json")
5. 控制器代码语法错误
控制器的HttpPost路由模板缺少闭合的},且return语句无返回值,会导致控制器动作执行失败,间接引发服务器无响应超时。
解决方法:
修正控制器代码:
[HttpPost("Report/{reportId}")] public async Task<IActionResult> AttachReport(string reportId) { Reporter client = new Reporter(); var response = await client.AttachReportToRequest(reportId); return Ok(response.StatusCode); // 根据实际需求返回合适结果 }
内容的提问来源于stack exchange,提问作者mr_ed87

