使用HTTPWebrequest上传文件(多部分/表单数据)

本文翻译自:Upload files with HTTPWebrequest (multipart/form-data)

Is there any class, library or some piece of code which will help me to upload files with HTTPWebrequest ? 是否有任何类,库或某些代码段可以帮助我使用HTTPWebrequest上传文件?

Edit 2: 编辑2:

I do not want to upload to a WebDAV folder or something like that. 我不想上传到WebDAV文件夹或类似的文件。 I want to simulate a browser, so just like you upload your avatar to a forum or upload a file via form in a web application. 我想模拟一个浏览器,就像您将头像上传到论坛或通过Web应用程序中的表单上传文件一样。 Upload to a form which uses a multipart/form-data. 上传到使用多部分/表单数据的表单。

Edit: 编辑:

WebClient is not cover my requirements, so I'm looking for a solution with HTTPWebrequest . WebClient不能满足我的要求,因此我正在寻找HTTPWebrequest解决方案。


#1楼

参考:https://stackoom.com/question/2NMU/使用HTTPWebrequest上传文件-多部分-表单数据


#2楼

Check out the MyToolkit library: 签出MyToolkit库:

var request = new HttpPostRequest("http://www.server.com");
request.Data.Add("name", "value"); // POST data
request.Files.Add(new HttpPostFile("name", "file.jpg", "path/to/file.jpg")); 

await Http.PostAsync(request, OnRequestFinished);

http://mytoolkit.codeplex.com/wikipage?title=Http http://mytoolkit.codeplex.com/wikipage?title=Http


#3楼

For me, the following works (mostly inspirated from all of the following answers), I started from Elad's answer and modify/simplify things to match my need (remove not file form inputs, only one file, ...). 对我来说,以下作品(大部分是从以下所有答案中得到启发),我从埃拉德的答案开始,并进行了修改/简化,以适应我的需要(不删除文件形式输入,仅删除一个文件,...)。

Hope it can helps somebody :) 希望它可以帮助某人:)

(PS: I know that exception handling is not implemented and it assumes that it was written inside a class, so I may need some integration effort...) (PS:我知道未实现异常处理,并且假定它是在类内部编写的,因此我可能需要一些集成工作...)

private void uploadFile()
    {
        Random rand = new Random();
        string boundary = "----boundary" + rand.Next().ToString();
        Stream data_stream;
        byte[] header = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"file_path\"; filename=\"" + System.IO.Path.GetFileName(this.file) + "\"\r\nContent-Type: application/octet-stream\r\n\r\n");
        byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");

        // Do the request
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(MBF_URL);
        request.UserAgent = "My Toolbox";
        request.Method = "POST";
        request.KeepAlive = true;
        request.ContentType = "multipart/form-data; boundary=" + boundary;
        data_stream = request.GetRequestStream();
        data_stream.Write(header, 0, header.Length);
        byte[] file_bytes = System.IO.File.ReadAllBytes(this.file);
        data_stream.Write(file_bytes, 0, file_bytes.Length);
        data_stream.Write(trailer, 0, trailer.Length);
        data_stream.Close();

        // Read the response
        WebResponse response = request.GetResponse();
        data_stream = response.GetResponseStream();
        StreamReader reader = new StreamReader(data_stream);
        this.url = reader.ReadToEnd();

        if (this.url == "") { this.url = "No response :("; }

        reader.Close();
        data_stream.Close();
        response.Close();
    }

#4楼

Based on the code provided above I added support for multiple files and also uploading a stream directly without the need to have a local file. 根据上面提供的代码,我添加了对多个文件的支持,并且还直接上传了流,而无需本地文件。

To upload files to a specific url including some post params do the following: 要将文件上传到特定的URL(包括一些发布参数),请执行以下操作:

RequestHelper.PostMultipart(
    "http://www.myserver.com/upload.php", 
    new Dictionary<string, object>() {
        { "testparam", "my value" },
        { "file", new FormFile() { Name = "image.jpg", ContentType = "image/jpeg", FilePath = "c:\\temp\\myniceimage.jpg" } },
        { "other_file", new FormFile() { Name = "image2.jpg", ContentType = "image/jpeg", Stream = imageDataStream } },
    });

To enhance this even more one could determine the name and mime type from the given file itself. 为了增强这一点,甚至可以从给定文件本身确定名称和mime类型。

public class FormFile 
{
    public string Name { get; set; }

    public string ContentType { get; set; }

    public string FilePath { get; set; }

    public Stream Stream { get; set; }
}

public class RequestHelper
{

    public static string PostMultipart(string url, Dictionary<string, object> parameters) {

        string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
        byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.ContentType = "multipart/form-data; boundary=" + boundary;
        request.Method = "POST";
        request.KeepAlive = true;
        request.Credentials = System.Net.CredentialCache.DefaultCredentials;

        if(parameters != null && parameters.Count > 0) {

            using(Stream requestStream = request.GetRequestStream()) {

                foreach(KeyValuePair<string, object> pair in parameters) {

                    requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
                    if(pair.Value is FormFile) {
                        FormFile file = pair.Value as FormFile;
                        string header = "Content-Disposition: form-data; name=\"" + pair.Key + "\"; filename=\"" + file.Name + "\"\r\nContent-Type: " + file.ContentType + "\r\n\r\n";
                        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(header);
                        requestStream.Write(bytes, 0, bytes.Length);
                        byte[] buffer = new byte[32768];
                        int bytesRead;
                        if(file.Stream == null) {
                            // upload from file
                            using(FileStream fileStream = File.OpenRead(file.FilePath)) {
                                while((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                                    requestStream.Write(buffer, 0, bytesRead);
                                fileStream.Close();
                            }
                        }
                        else {
                            // upload from given stream
                            while((bytesRead = file.Stream.Read(buffer, 0, buffer.Length)) != 0)
                                requestStream.Write(buffer, 0, bytesRead);
                        }
                    }
                    else {
                        string data = "Content-Disposition: form-data; name=\"" + pair.Key + "\"\r\n\r\n" + pair.Value;
                        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
                        requestStream.Write(bytes, 0, bytes.Length);
                    }
                }

                byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
                requestStream.Write(trailer, 0, trailer.Length);
                requestStream.Close();
            }
        }

        using(WebResponse response = request.GetResponse()) {
            using(Stream responseStream = response.GetResponseStream())
            using(StreamReader reader = new StreamReader(responseStream))
                return reader.ReadToEnd();
        }


    }
}

#5楼

UPDATE: Using .NET 4.5 (or .NET 4.0 by adding the Microsoft.Net.Http package from NuGet) this is possible without external code, extensions, and "low level" HTTP manipulation. 更新:使用.NET 4.5(或通过从NuGet添加Microsoft.Net.Http包的.NET 4.0),无需外部代码,扩展名和“低级” HTTP操作就可以实现此目的。 Here is an example: 这是一个例子:

// Perform the equivalent of posting a form with a filename and two files, in HTML:
// <form action="{url}" method="post" enctype="multipart/form-data">
//     <input type="text" name="filename" />
//     <input type="file" name="file1" />
//     <input type="file" name="file2" />
// </form>
private async Task<System.IO.Stream> UploadAsync(string url, string filename, Stream fileStream, byte [] fileBytes)
{
    // Convert each of the three inputs into HttpContent objects

    HttpContent stringContent = new StringContent(filename);
    // examples of converting both Stream and byte [] to HttpContent objects
    // representing input type file
    HttpContent fileStreamContent = new StreamContent(fileStream);
    HttpContent bytesContent = new ByteArrayContent(fileBytes);

    // Submit the form using HttpClient and 
    // create form data as Multipart (enctype="multipart/form-data")

    using (var client = new HttpClient())
    using (var formData = new MultipartFormDataContent()) 
    {
        // Add the HttpContent objects to the form data

        // <input type="text" name="filename" />
        formData.Add(stringContent, "filename", "filename");
        // <input type="file" name="file1" />
        formData.Add(fileStreamContent, "file1", "file1");
        // <input type="file" name="file2" />
        formData.Add(bytesContent, "file2", "file2");

        // Invoke the request to the server

        // equivalent to pressing the submit button on
        // a form with attributes (action="{url}" method="post")
        var response = await client.PostAsync(url, formData);

        // ensure the request was a success
        if (!response.IsSuccessStatusCode)
        {
            return null;
        }
        return await response.Content.ReadAsStreamAsync();
    }
}

#6楼

I realize this is probably really late, but I was searching for the same solution. 我意识到这可能真的很晚,但是我正在寻找相同的解决方案。 I found the following response from a Microsoft rep 我从Microsoft代表处发现以下回应

private void UploadFilesToRemoteUrl(string url, string[] files, string logpath, NameValueCollection nvc)
{

    long length = 0;
    string boundary = "----------------------------" +
    DateTime.Now.Ticks.ToString("x");


    HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
    httpWebRequest2.ContentType = "multipart/form-data; boundary=" +
    boundary;
    httpWebRequest2.Method = "POST";
    httpWebRequest2.KeepAlive = true;
    httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials;



    Stream memStream = new System.IO.MemoryStream();
    byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");


    string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

    foreach(string key in nvc.Keys)
    {
        string formitem = string.Format(formdataTemplate, key, nvc[key]);
        byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
        memStream.Write(formitembytes, 0, formitembytes.Length);
    }


    memStream.Write(boundarybytes,0,boundarybytes.Length);

    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";

    for(int i=0;i<files.Length;i++)
    {

        string header = string.Format(headerTemplate,"file"+i,files[i]);
        byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
        memStream.Write(headerbytes,0,headerbytes.Length);


        FileStream fileStream = new FileStream(files[i], FileMode.Open,
        FileAccess.Read);
        byte[] buffer = new byte[1024];

        int bytesRead = 0;

        while ( (bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0 )
        {
            memStream.Write(buffer, 0, bytesRead);
        }


        memStream.Write(boundarybytes,0,boundarybytes.Length);


        fileStream.Close();
    }

    httpWebRequest2.ContentLength = memStream.Length;
    Stream requestStream = httpWebRequest2.GetRequestStream();

    memStream.Position = 0;
    byte[] tempBuffer = new byte[memStream.Length];
    memStream.Read(tempBuffer,0,tempBuffer.Length);
    memStream.Close();
    requestStream.Write(tempBuffer,0,tempBuffer.Length );
    requestStream.Close();


    WebResponse webResponse2 = httpWebRequest2.GetResponse();

    Stream stream2 = webResponse2.GetResponseStream();
    StreamReader reader2 = new StreamReader(stream2);

    webResponse2.Close();
    httpWebRequest2 = null;
    webResponse2 = null;

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C# WinForm 应用程序中,可以使用 HttpWebRequest 类来实现表单上传文件,具体步骤如下: 1. 创建 HttpWebRequest 对象,并设置请求参数。同时创建一个 NameValueCollection 对象用于存储表单数据。 ```csharp HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uploadUrl); request.Method = "POST"; request.ContentType = "multipart/form-data"; NameValueCollection formData = new NameValueCollection(); ``` 2. 将表单数据添加到 NameValueCollection 对象中。 ```csharp formData.Add("key1", "value1"); formData.Add("key2", "value2"); ``` 3. 构造要上传的文件数据。 ```csharp byte[] fileData = File.ReadAllBytes(filePath); string fileName = Path.GetFileName(filePath); string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n"; string formdata = string.Format(formdataTemplate, "file", fileName); byte[] formdataBytes = Encoding.UTF8.GetBytes(formdata); byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); ``` 4. 将表单数据和文件数据写入请求流中。 ```csharp Stream requestStream = request.GetRequestStream(); foreach (string key in formData.Keys) { string formItem = string.Format("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", key, formData[key]); byte[] formItemBytes = Encoding.UTF8.GetBytes(formItem); requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); requestStream.Write(formItemBytes, 0, formItemBytes.Length); } requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); requestStream.Write(formdataBytes, 0, formdataBytes.Length); requestStream.Write(fileData, 0, fileData.Length); byte[] trailer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); requestStream.Write(trailer, 0, trailer.Length); requestStream.Close(); ``` 5. 发送请求并获取响应。 ```csharp HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string responseString = reader.ReadToEnd(); reader.Close(); response.Close(); ``` 完整的代码示例如下: ```csharp public void UploadFileWithForm(string uploadUrl, string filePath) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uploadUrl); request.Method = "POST"; request.ContentType = "multipart/form-data"; NameValueCollection formData = new NameValueCollection(); formData.Add("key1", "value1"); formData.Add("key2", "value2"); byte[] fileData = File.ReadAllBytes(filePath); string fileName = Path.GetFileName(filePath); string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n"; string formdata = string.Format(formdataTemplate, "file", fileName); byte[] formdataBytes = Encoding.UTF8.GetBytes(formdata); byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); Stream requestStream = request.GetRequestStream(); foreach (string key in formData.Keys) { string formItem = string.Format("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", key, formData[key]); byte[] formItemBytes = Encoding.UTF8.GetBytes(formItem); requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); requestStream.Write(formItemBytes, 0, formItemBytes.Length); } requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); requestStream.Write(formdataBytes, 0, formdataBytes.Length); requestStream.Write(fileData, 0, fileData.Length); byte[] trailer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); requestStream.Write(trailer, 0, trailer.Length); requestStream.Close(); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string responseString = reader.ReadToEnd(); reader.Close(); response.Close(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值