一、 multipart/form-data简介
在Web开发中,当需要上传文件或二进制数据时,我们通常会使用multipart/form-data来实现。它是一种HTTP请求方式,用于将表单数据以及二进制文件一并提交到服务器端。
当使用multipart/form-data来上传文件时,我们需要在HTTP请求中包含数据流。这些数据流包含有文件本身的二进制数据以及文件名、文件大小等信息。
二、如何正确地使用multipart/form-data?
1. 创建multipart/form-data POST请求
public static void Post(string url, string postData, string file, string fileName) { 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"); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url)); request.Method = "POST"; request.ContentType = "multipart/form-data; boundary=" + boundary; request.KeepAlive = true; Stream requestStream = request.GetRequestStream(); // 将post数据写入request stream if (!string.IsNullOrEmpty(postData)) { byte[] postDataBytes = System.Text.Encoding.UTF8.GetBytes(postData); requestStream.Write(postDataBytes, 0, postDataBytes.Length); requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); } // 将文件写入request stream if (!string.IsNullOrEmpty(file)) { FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[4096]; int bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { requestStream.Write(buffer, 0, bytesRead); } fileStream.Close(); requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); // 添加文件头信息 string header = "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\nContent-Type: application/octet-stream\r\n\r\n"; byte[] headerBytes = System.Text.Encoding.UTF8.GetBytes(header); requestStream.Write(headerBytes, 0, headerBytes.Length); } requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); requestStream.Close(); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (StreamReader reader = new StreamReader(response.GetResponseStream())) { Console.WriteLine(reader.ReadToEnd()); } }
在以上示例中,我们创建了一个multipart/form-data格式的POST请求,请求内容包括postData和file两个部分,其中postData为表单数据,file为二进制文件数据。
2.实例:上传文件
public static void UploadFile(string url, string filePath) { HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; request.Method = "POST"; request.ContentType = "multipart/form-data"; FileInfo fileInfo = new FileInfo(filePath); byte[] fileContents = new byte[fileInfo.Length]; using (FileStream fs = fileInfo.OpenRead()) { fs.Read(fileContents, 0, fileContents.Length); } string boundary = DateTime.Now.Ticks.ToString("x"); byte[] boundaryBytes = Encoding.ASCII.GetBytes($"--{boundary}\r\n"); request.ContentLength = boundaryBytes.Length * 2 + fileContents.Length; using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); string contentDisposition = "Content-Disposition: form-data; " + $"name=\"{fileInfo.Name}\"; filename=\"{fileInfo.Name}\"\r\nContent-Type: application/octet-stream\r\n\r\n"; byte[] headerBytes = Encoding.ASCII.GetBytes(contentDisposition); requestStream.Write(headerBytes, 0, headerBytes.Length); requestStream.Write(fileContents, 0, fileContents.Length); requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); } HttpWebResponse response = request.GetResponse() as HttpWebResponse; using (Stream responseStream = response.GetResponseStream()) { StreamReader reader = new StreamReader(responseStream); Console.WriteLine(reader.ReadToEnd()); } }
以上是C#上传文件的示例,其中我们通过HttpWebRequest对象创建了一个multipart/form-data的POST请求,请求内容包括请求头和二进制文件数据。
3.实例:上传文件和文本数据
public static void UploadFileAndData() { string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); string header = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"file\"; filename=\"test.png\"\r\nContent-Type: image/png\r\n\r\n"; string footer = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"description\"\r\n\r\nthis is a test\r\n--" + boundary + "--\r\n"; byte[] headerBytes = Encoding.UTF8.GetBytes(header); byte[] footerBytes = Encoding.UTF8.GetBytes(footer); byte[] fileBytes; using (FileStream fileStream = File.OpenRead("test.png")) { fileBytes = new byte[fileStream.Length]; fileStream.Read(fileBytes, 0, fileBytes.Length); } HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://example.com/upload"); request.ContentType = "multipart/form-data; boundary=" + boundary; request.Method = "POST"; request.ContentLength = headerBytes.Length + fileBytes.Length + footerBytes.Length; using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(headerBytes, 0, headerBytes.Length); requestStream.Write(fileBytes, 0, fileBytes.Length); requestStream.Write(footerBytes, 0, footerBytes.Length); } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); string result; using (StreamReader reader = new StreamReader(response.GetResponseStream())) { result = reader.ReadToEnd(); } Console.WriteLine(result); }
以上示例演示了如何同时上传文件和文本数据,使用了multipart/form-data的格式。其中请求数据分为三部分:请求头、上传文件数据和文本数据。
三、总结
通过以上示例,我们可以了解如何在C#中正确地使用multipart/form-data格式。这种格式广泛应用于文件上传和表单提交。需要注意的是,在使用multipart/form-data时,我们需要特别处理请求内容并使用正确的Content-Type头部。