如何通过 HttpWebRequest 上传文件?

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何通过 HttpWebRequest 上传文件?相关的知识,希望对你有一定的参考价值。

咨询区

  • dr. evil

我不希望通过 WebDAV 文件夹的方式上传文件,我想通过相关的 HttpWebRequest 类,类库或者代码片段来帮我模拟浏览器行为来上传文件,请问是否有好的解决方案?

回答区

  • Joshcodes

如果你用的是基于 .NET 4.5 以上的版本,直接从 NuGet 上引用 Microsoft.Net.Http 工具包即可,不需要任何扩展代码,外部代码或者 HTTP 低级别的代码,参考如下例子:

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();
    
  • Stefan

关于文件上传,除了单文件,我的类库中还支持多文件上传,无本地文件的流上传,参考下面代码:

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();
        


    

然后像下面这样使用。

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  ,
    );

点评区

这是一个老问题了,不过谈灵活莫过于 HttpWebRequest

以上是关于如何通过 HttpWebRequest 上传文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 HttpWebRequest 模拟浏览器文件上传

HttpClient 与 HttpWebRequest

winform HttpWebRequest上传文件

C# HttpWebRequest 表单上传

上传速度问题:HttpWebRequest [重复]

使用 HttpWebRequest,将文件上传到 SharePoint 时,WebResponse 是未编译的 aspx 页面