文件上传至C# .Net Core API时接口收到文件为null问题排查
问题原因
multipart/form-data报文格式不符合规范:该格式要求必须指定边界分隔符(boundary),且报文内容需要按照边界分隔符 + 表单字段声明 + 空行 + 文件内容 + 结束边界的格式组装,你直接把原始文件流写入请求体,没有携带files表单字段的相关声明,服务端无法匹配到接口定义的files参数,自然返回null。
- 请求流提前关闭:你在while循环内部调用了
requestStream.Close(),第一次读取写入完成后就直接关闭了流,就算后续还有未读完的内容也无法写入,甚至会直接抛出异常。
- 请求流提前关闭:你在while循环内部调用了
- ContentLength设置错误:你直接赋值为原始文件流的长度,但
multipart/form-data格式的请求体总长度包含了边界、字段声明等额外内容,实际长度大于原始文件长度,错误的长度会导致服务端接收的报文不完整。
- ContentLength设置错误:你直接赋值为原始文件流的长度,但
- ContentType未指定boundary:你只设置了
request.ContentType = "multipart/form-data",没有补充对应的boundary参数,服务端不知道用什么分隔符解析报文。
- ContentType未指定boundary:你只设置了
修正后的代码
public static void SendFile(Stream DATA, string fileName = "upload.bin") { // 生成随机边界符 string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); byte[] endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL); request.Method = "POST"; // ContentType带上边界符 request.ContentType = "multipart/form-data; boundary=" + boundary; request.KeepAlive = true; using (Stream requestStream = request.GetRequestStream()) { // 1. 写入边界符 requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); // 2. 写入表单字段声明,对应接口的files参数 string formHeader = "Content-Disposition: form-data; name=\"files\"; filename=\"" + fileName + "\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n"; byte[] formHeaderBytes = System.Text.Encoding.UTF8.GetBytes(formHeader); requestStream.Write(formHeaderBytes, 0, formHeaderBytes.Length); // 3. 写入文件内容 byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = DATA.Read(buffer, 0, buffer.Length)) > 0) { requestStream.Write(buffer, 0, bytesRead); } // 4. 写入结束边界 requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); } // 读取响应 using (WebResponse webResponse = request.GetResponse()) using (Stream webStream = webResponse.GetResponseStream()) using (StreamReader responseReader = new StreamReader(webStream)) { string response = responseReader.ReadToEnd(); Console.Out.WriteLine(response); } } catch (Exception e) { Console.Out.WriteLine("-----------------"); Console.Out.WriteLine(e.Message); } }
额外优化建议
如果是.NET Core/.NET 5+的项目,更推荐使用HttpClient代替已经过时的HttpWebRequest,HttpClient有现成的MultipartFormDataContent类可以自动处理multipart格式的组装,不需要手动拼接边界和报文内容,出错概率更低。
内容的提问来源于stack exchange,提问作者TheWizardOfTN
相关产品推荐
相关产品推荐

