Upload files with HTTPWebrequest (multipart/form-data)

后端 未结 21 3068
独厮守ぢ
独厮守ぢ 2020-11-21 04:53

Is there any class, library or some piece of code which will help me to upload files with HTTPWebrequest?

Edit 2:

I do not

相关标签:
21条回答
  • 2020-11-21 05:15

    I was looking for something like this, Found in : http://bytes.com/groups/net-c/268661-how-upload-file-via-c-code (modified for correctness):

    public static string UploadFilesToRemoteUrl(string url, string[] files, NameValueCollection formFields = null)
    {
        string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
    
        HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
        request.ContentType = "multipart/form-data; boundary=" +
                                boundary;
        request.Method = "POST";
        request.KeepAlive = true;
    
        Stream memStream = new System.IO.MemoryStream();
    
        var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
                                                                boundary + "\r\n");
        var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
                                                                    boundary + "--");
    
    
        string formdataTemplate = "\r\n--" + boundary +
                                    "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
    
        if (formFields != null)
        {
            foreach (string key in formFields.Keys)
            {
                string formitem = string.Format(formdataTemplate, key, formFields[key]);
                byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
                memStream.Write(formitembytes, 0, formitembytes.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++)
        {
            memStream.Write(boundarybytes, 0, boundarybytes.Length);
            var header = string.Format(headerTemplate, "uplTheFile", files[i]);
            var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
    
            memStream.Write(headerbytes, 0, headerbytes.Length);
    
            using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))
            {
                var buffer = new byte[1024];
                var bytesRead = 0;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                }
            }
        }
    
        memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
        request.ContentLength = memStream.Length;
    
        using (Stream requestStream = request.GetRequestStream())
        {
            memStream.Position = 0;
            byte[] tempBuffer = new byte[memStream.Length];
            memStream.Read(tempBuffer, 0, tempBuffer.Length);
            memStream.Close();
            requestStream.Write(tempBuffer, 0, tempBuffer.Length);
        }
    
        using (var response = request.GetResponse())
        {
            Stream stream2 = response.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            return reader2.ReadToEnd();
        }
    }
    
    0 讨论(0)
  • 2020-11-21 05:16

    My ASP.NET Upload FAQ has an article on this, with example code: Upload files using an RFC 1867 POST request with HttpWebRequest/WebClient. This code doesn't load files into memory (as opposed to the code above), supports multiple files, and supports form values, setting credentials and cookies, etc.

    Edit: looks like Axosoft took down the page. Thanks guys.

    It's still accessible via archive.org.

    0 讨论(0)
  • 2020-11-21 05:19

    Took the code above and fixed because it throws Internal Server Error 500. There are some problems with \r\n badly positioned and spaces etc. Applied the refactoring with memory stream, writing directly to the request stream. Here is the result:

        public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {
            log.Debug(string.Format("Uploading {0} to {1}", file, url));
            string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
            byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
    
            HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
            wr.ContentType = "multipart/form-data; boundary=" + boundary;
            wr.Method = "POST";
            wr.KeepAlive = true;
            wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
    
            Stream rs = wr.GetRequestStream();
    
            string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
            foreach (string key in nvc.Keys)
            {
                rs.Write(boundarybytes, 0, boundarybytes.Length);
                string formitem = string.Format(formdataTemplate, key, nvc[key]);
                byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
                rs.Write(formitembytes, 0, formitembytes.Length);
            }
            rs.Write(boundarybytes, 0, boundarybytes.Length);
    
            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
            string header = string.Format(headerTemplate, paramName, file, contentType);
            byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
            rs.Write(headerbytes, 0, headerbytes.Length);
    
            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) {
                rs.Write(buffer, 0, bytesRead);
            }
            fileStream.Close();
    
            byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
            rs.Write(trailer, 0, trailer.Length);
            rs.Close();
    
            WebResponse wresp = null;
            try {
                wresp = wr.GetResponse();
                Stream stream2 = wresp.GetResponseStream();
                StreamReader reader2 = new StreamReader(stream2);
                log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
            } catch(Exception ex) {
                log.Error("Error uploading file", ex);
                if(wresp != null) {
                    wresp.Close();
                    wresp = null;
                }
            } finally {
                wr = null;
            }
        }
    

    and sample usage:

        NameValueCollection nvc = new NameValueCollection();
        nvc.Add("id", "TTR");
        nvc.Add("btn-submit-photo", "Upload");
        HttpUploadFile("http://your.server.com/upload", 
             @"C:\test\test.jpg", "file", "image/jpeg", nvc);
    

    It could be extended to handle multiple files or just call it multiple times for each file. However it suits your needs.

    0 讨论(0)
  • 2020-11-21 05:19

    I think you're looking for something more like WebClient.

    Specifically, UploadFile().

    0 讨论(0)
  • 2020-11-21 05:20

    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...)

    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();
        }
    
    0 讨论(0)
  • 2020-11-21 05:22

    Check out the MyToolkit library:

    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

    0 讨论(0)
提交回复
热议问题