您的位置:

如何正确地使用C#中的multipart/form-data?- 以示例代码为主的使用指南

一、 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头部。