C#.NET使用multipart/form-data方式上传文件及其他数据
请求发起
.NET Framework 3.5 版
1 const string CRLF = "\r\n"; 2 3 /// <summary> 4 /// 使用multipart/form-data方式上传文件及提交其他数据 5 /// </summary> 6 /// <param name="headers">请求头参数</param> 7 /// <param name="nameValueCollection">键值对参数</param> 8 /// <param name="fileCollection">文件参数:参数名,文件路径</param> 9 /// <returns>接口返回结果</returns> 10 public static string UploadMultipartFormData(string url, string httpMethod, Dictionary<string, string> headers, NameValueCollection nameValueCollection, NameValueCollection fileCollection) 11 { 12 var boundary = string.Format("batch_{0}", Guid.NewGuid()); 13 var startBoundary = string.Format("--{0}", boundary); 14 15 // Set up Request body. 16 WebRequest request = HttpWebRequest.Create(url); 17 foreach (var item in headers) 18 { 19 request.Headers.Add(item.Key, item.Value); 20 } 21 request.Method = httpMethod; 22 23 request.ContentType = $"multipart/form-data; boundary={boundary}"; 24 25 // Writes the boundary and Content-Disposition header, then writes 26 // the file binary, and finishes by writing the closing boundary. 27 using (Stream requestStream = request.GetRequestStream()) 28 { 29 StreamWriter writer = new StreamWriter(requestStream); 30 31 // 处理文件内容 32 string[] fileKeys = fileCollection.AllKeys; 33 foreach (string key in fileKeys) 34 { 35 WriteFileToStream(writer, startBoundary, key, fileCollection[key]); 36 } 37 38 // 键值对参数 39 string[] allKeys = nameValueCollection.AllKeys; 40 foreach (string key in allKeys) 41 { 42 WriteNvToStream(writer, startBoundary, key, nameValueCollection[key]); 43 } 44 45 var endFormData = CRLF + string.Format("--{0}--", boundary) + CRLF; 46 47 writer.Write(endFormData); 48 writer.Flush(); 49 writer.Close(); 50 } 51 52 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 53 string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); 54 55 return json; 56 } 57 58 static void WriteFileToStream(StreamWriter writer, string startBoundary, string name, string filePath) 59 { 60 var filename = Path.GetFileName(filePath); 61 var fileRequestBody = startBoundary + CRLF; 62 fileRequestBody += $"Content-Disposition: form-data; name=\"{name}\"; filename=\"{filename}\"" + CRLF + CRLF; 63 64 writer.Write(fileRequestBody); 65 writer.Flush(); 66 67 byte[] bmpBytes = File.ReadAllBytes(filePath); 68 writer.BaseStream.Write(bmpBytes, 0, bmpBytes.Length); 69 } 70 71 static void WriteNvToStream(StreamWriter writer, string startBoundary, string name, string value) 72 { 73 var nvFormData = CRLF + startBoundary + CRLF; 74 nvFormData += $"Content-Disposition: form-data; name=\"{name}\"" + CRLF + CRLF; 75 nvFormData += value /*+ CRLF*/; 76 77 writer.Write(nvFormData); 78 writer.Flush(); 79 }
.NET Framework 4.+ 版
1 /// <summary>
2 /// 使用multipart/form-data方式上传文件及其他数据
3 /// </summary>
4 /// <param name="headers">请求头参数</param>
5 /// <param name="nameValueCollection">键值对参数</param>
6 /// <param name="fileCollection">文件参数:参数名,文件路径</param>
7 /// <returns>接口返回结果</returns>
8 public static string PostMultipartFormData(string url, Dictionary<string, string> headers, NameValueCollection nameValueCollection, NameValueCollection fileCollection)
9 {
10 using (var client = new HttpClient())
11 {
12 foreach (var item in headers)
13 {
14 client.DefaultRequestHeaders.Add(item.Key, item.Value);
15 }
16
17 using (var content = new MultipartFormDataContent())
18 {
19 // 键值对参数
20 string[] allKeys = nameValueCollection.AllKeys;
21 foreach (string key in allKeys)
22 {
23 var dataContent = new ByteArrayContent(Encoding.UTF8.GetBytes(nameValueCollection[key]));
24 dataContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
25 {
26 Name = key
27 };
28 content.Add(dataContent);
29 }
30
31 //处理文件内容
32 string[] fileKeys = fileCollection.AllKeys;
33 foreach (string key in fileKeys)
34 {
35 byte[] bmpBytes = File.ReadAllBytes(fileCollection[key]);
36 var fileContent = new ByteArrayContent(bmpBytes);//填充文件字节
37 fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
38 {
39 Name = key,
40 FileName = Path.GetFileName(fileCollection[key])
41 };
42 content.Add(fileContent);
43 }
44
45 var result = client.PostAsync(url, content).Result;//post请求
46 string data = result.Content.ReadAsStringAsync().Result;
47 return data;//返回操作结果
48 }
49 }
50 }
Web API 接收接口
ASP .NET Core Web API 接口接收 multipart/form-data 文件、数据
1 [HttpPost] 2 //public string Post([FromForm] string directory, [FromForm] IList<IFormFile> files ) 3 public string Post([FromForm] string directory, [FromForm] IFormFile files) 4 { 5 return ""; 6 } 7 8 [HttpPut] 9 public string Put([FromForm] IFormFile templateFile, [FromForm] string id, [FromForm] string objectVersionNumber) 10 { 11 return ""; 12 }
ASP.NET 4.x 版
1 [HttpPost(Name = "PostWeatherForecast")] 2 //public string Post([FromForm] string directory, [FromForm] IList<IFormFile> files ) 3 public string Post([FromForm] string directory, [FromForm] IFormFile files) 4 { 5 // Check if the request contains multipart/form-data. 6 if (!Request.ContentType.IsMimeMultipartContent()) 7 { 8 throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); 9 } 10 11 string root = Request.HttpContext.Current.Server.MapPath("~/App_Data"); 12 var provider = new MultipartFormDataStreamProvider(root); 13 14 try 15 { 16 // Read the form data. 17 await Request.Content.ReadAsMultipartAsync(provider); 18 19 // This illustrates how to get the file names. 20 //foreach (MultipartFileData file in provider.FileData) 21 //{ 22 // Trace.WriteLine(file.Headers.ContentDisposition.FileName); 23 // Trace.WriteLine("Server file path: " + file.LocalFileName); 24 //} 25 // return Request.CreateResponse(HttpStatusCode.OK); 26 } 27 catch (System.Exception e) 28 { 29 // return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); 30 } 31 32 return ""; 33 }
https://docs.microsoft.com/zh-cn/aspnet/web-api/overview/advanced/sending-html-form-data-part-2