Upload files with HTTPWebrequest (multipart/form-data)

后端 未结 21 2566
独厮守ぢ
独厮守ぢ 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:24

    I realize this is probably really late, but I was searching for the same solution. I found the following response from a Microsoft rep

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

    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:

    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.

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

    Client use convert File to ToBase64String, after use Xml to promulgate to Server call, this server use File.WriteAllBytes(path,Convert.FromBase64String(dataFile_Client_sent)).

    Good lucky!

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

    Took the above and modified it accept some header values, and multiple files

        NameValueCollection headers = new NameValueCollection();
            headers.Add("Cookie", "name=value;");
            headers.Add("Referer", "http://google.com");
        NameValueCollection nvc = new NameValueCollection();
            nvc.Add("name", "value");
    
        HttpUploadFile(url, new string[] { "c:\\file1.txt", "c:\\file2.jpg" }, new string[] { "file", "image" }, new string[] { "application/octet-stream", "image/jpeg" }, nvc, headers);
    

    public static void HttpUploadFile(string url, string[] file, string[] paramName, string[] contentType, NameValueCollection nvc, NameValueCollection headerItems)
    {
        //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);
    
        foreach (string key in headerItems.Keys)
        {
            if (key == "Referer")
            {
                wr.Referer = headerItems[key];
            }
            else
            {
                wr.Headers.Add(key, headerItems[key]);
            }
        }
    
        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 = "";
    
        for(int i =0; i<file.Count();i++)
        {
            header = string.Format(headerTemplate, paramName[i], System.IO.Path.GetFileName(file[i]), contentType[i]);
            byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
            rs.Write(headerbytes, 0, headerbytes.Length);
    
            FileStream fileStream = new FileStream(file[i], 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();
            rs.Write(boundarybytes, 0, boundarybytes.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);
                wresp.Close();
                wresp = null;
        }
        finally
        {
            wr = null;
        }
    }
    
    0 讨论(0)
  • 2020-11-21 05:30

    I wrote a class using WebClient way back when to do multipart form upload.

    http://ferozedaud.blogspot.com/2010/03/multipart-form-upload-helper.html

    /// 
    /// MimePart
    /// Abstract class for all MimeParts
    /// 
    
    abstract class MimePart
    {
        public string Name { get; set; }
    
        public abstract string ContentDisposition { get; }
    
        public abstract string ContentType { get; }
    
        public abstract void CopyTo(Stream stream);
    
        public String Boundary
        {
            get;
            set;
        }
    }
    
    class NameValuePart : MimePart
    {
        private NameValueCollection nameValues;
    
        public NameValuePart(NameValueCollection nameValues)
        {
            this.nameValues = nameValues;
        }
    
        public override void CopyTo(Stream stream)
        {
            string boundary = this.Boundary;
            StringBuilder sb = new StringBuilder();
    
            foreach (object element in this.nameValues.Keys)
            {
                sb.AppendFormat("--{0}", boundary);
                sb.Append("\r\n");
                sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\";", element);
                sb.Append("\r\n");
                sb.Append("\r\n");
                sb.Append(this.nameValues[element.ToString()]);
    
                sb.Append("\r\n");
    
            }
    
            sb.AppendFormat("--{0}", boundary);
            sb.Append("\r\n");
    
            //Trace.WriteLine(sb.ToString());
            byte [] data = Encoding.ASCII.GetBytes(sb.ToString());
            stream.Write(data, 0, data.Length);
        }
    
        public override string ContentDisposition
        {
            get { return "form-data"; }
        }
    
        public override string ContentType
        {
            get { return String.Empty; }
        }
    } 
    
    class FilePart : MimePart
    
    {
    
        private Stream input;
    
        private String contentType;
    
    
    
        public FilePart(Stream input, String name, String contentType)
    
        {
    
            this.input = input;
    
            this.contentType = contentType;
    
            this.Name = name;
    
        }
    
    
    
        public override void CopyTo(Stream stream)
    
        {
    
            StringBuilder sb = new StringBuilder();
    
            sb.AppendFormat("Content-Disposition: {0}", this.ContentDisposition);
    
            if (this.Name != null)
    
                sb.Append("; ").AppendFormat("name=\"{0}\"", this.Name);
    
            if (this.FileName != null)
    
                sb.Append("; ").AppendFormat("filename=\"{0}\"", this.FileName);
    
            sb.Append("\r\n");
    
            sb.AppendFormat(this.ContentType);
    
            sb.Append("\r\n");
    
            sb.Append("\r\n");
    
    
    
        // serialize the header data.
    
        byte[] buffer = Encoding.ASCII.GetBytes(sb.ToString());
    
        stream.Write(buffer, 0, buffer.Length);
    
    
    
        // send the stream.
    
        byte[] readBuffer = new byte[1024];
    
        int read = input.Read(readBuffer, 0, readBuffer.Length);
    
        while (read > 0)
    
        {
    
            stream.Write(readBuffer, 0, read);
    
            read = input.Read(readBuffer, 0, readBuffer.Length);
    
        }
    
    
    
        // write the terminating boundary
    
        sb.Length = 0;
    
        sb.Append("\r\n");
    
        sb.AppendFormat("--{0}", this.Boundary);
    
        sb.Append("\r\n");
    
        buffer = Encoding.ASCII.GetBytes(sb.ToString());
    
        stream.Write(buffer, 0, buffer.Length);
    
    
    
    }
    
     public override string ContentDisposition
     {
          get { return "file"; }
     }
    
    
    
     public override string ContentType
     {
        get { 
           return String.Format("content-type: {0}", this.contentType); 
         }
     }
    
     public String FileName { get; set; }
    
    }
    
        /// 
        /// Helper class that encapsulates all file uploads
        /// in a mime part.
        /// 
    
        class FilesCollection : MimePart
        {
            private List files;
    
            public FilesCollection()
            {
                this.files = new List();
                this.Boundary = MultipartHelper.GetBoundary();
            }
    
            public int Count
            {
                get { return this.files.Count; }
            }
    
            public override string ContentDisposition
            {
                get
                {
                    return String.Format("form-data; name=\"{0}\"", this.Name);
                }
            }
    
            public override string ContentType
            {
                get { return String.Format("multipart/mixed; boundary={0}", this.Boundary); }
            }
    
            public override void CopyTo(Stream stream)
            {
                // serialize the headers
                StringBuilder sb = new StringBuilder(128);
                sb.Append("Content-Disposition: ").Append(this.ContentDisposition).Append("\r\n");
                sb.Append("Content-Type: ").Append(this.ContentType).Append("\r\n");
                sb.Append("\r\n");
                sb.AppendFormat("--{0}", this.Boundary).Append("\r\n");
    
                byte[] headerBytes = Encoding.ASCII.GetBytes(sb.ToString());
                stream.Write(headerBytes, 0, headerBytes.Length);
                foreach (FilePart part in files)
                {
                    part.Boundary = this.Boundary;
                    part.CopyTo(stream);
                }
            }
    
            public void Add(FilePart part)
            {
                this.files.Add(part);
            }
        }
    
    /// 
    /// Helper class to aid in uploading multipart
    /// entities to HTTP web endpoints.
    /// 
    
    class MultipartHelper
    {
        private static Random random = new Random(Environment.TickCount);
    
        private List formData = new List();
        private FilesCollection files = null;
        private MemoryStream bufferStream = new MemoryStream();
        private string boundary;
    
        public String Boundary { get { return boundary; } }
    
        public static String GetBoundary()
        {
            return Environment.TickCount.ToString("X");
        }
    
        public MultipartHelper()
        {
            this.boundary = MultipartHelper.GetBoundary();
        }
    
        public void Add(NameValuePart part)
        {
            this.formData.Add(part);
            part.Boundary = boundary;
        }
    
        public void Add(FilePart part)
        {
            if (files == null)
            {
                files = new FilesCollection();
            }
            this.files.Add(part);
        }
    
        public void Upload(WebClient client, string address, string method)
        {
            // set header
            client.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + this.boundary);
            Trace.WriteLine("Content-Type: multipart/form-data; boundary=" + this.boundary + "\r\n");
    
            // first, serialize the form data
            foreach (NameValuePart part in this.formData)
            {
                part.CopyTo(bufferStream);
            }
    
            // serialize the files.
            this.files.CopyTo(bufferStream);
    
            if (this.files.Count > 0)
            {
                // add the terminating boundary.
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("--{0}", this.Boundary).Append("\r\n");
                byte [] buffer = Encoding.ASCII.GetBytes(sb.ToString());
                bufferStream.Write(buffer, 0, buffer.Length);
            }
    
            bufferStream.Seek(0, SeekOrigin.Begin);
    
            Trace.WriteLine(Encoding.ASCII.GetString(bufferStream.ToArray()));
            byte [] response = client.UploadData(address, method, bufferStream.ToArray());
            Trace.WriteLine("----- RESPONSE ------");
            Trace.WriteLine(Encoding.ASCII.GetString(response));
        }
    
        /// 
        /// Helper class that encapsulates all file uploads
        /// in a mime part.
        /// 
    
        class FilesCollection : MimePart
        {
            private List files;
    
            public FilesCollection()
            {
                this.files = new List();
                this.Boundary = MultipartHelper.GetBoundary();
            }
    
            public int Count
            {
                get { return this.files.Count; }
            }
    
            public override string ContentDisposition
            {
                get
                {
                    return String.Format("form-data; name=\"{0}\"", this.Name);
                }
            }
    
            public override string ContentType
            {
                get { return String.Format("multipart/mixed; boundary={0}", this.Boundary); }
            }
    
            public override void CopyTo(Stream stream)
            {
                // serialize the headers
                StringBuilder sb = new StringBuilder(128);
                sb.Append("Content-Disposition: ").Append(this.ContentDisposition).Append("\r\n");
                sb.Append("Content-Type: ").Append(this.ContentType).Append("\r\n");
                sb.Append("\r\n");
                sb.AppendFormat("--{0}", this.Boundary).Append("\r\n");
    
                byte[] headerBytes = Encoding.ASCII.GetBytes(sb.ToString());
                stream.Write(headerBytes, 0, headerBytes.Length);
                foreach (FilePart part in files)
                {
                    part.Boundary = this.Boundary;
                    part.CopyTo(stream);
                }
            }
    
            public void Add(FilePart part)
            {
                this.files.Add(part);
            }
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Trace.Listeners.Add(new ConsoleTraceListener());
            try
            {
                using (StreamWriter sw = new StreamWriter("testfile.txt", false))
                {
                    sw.Write("Hello there!");
                }
    
                using (Stream iniStream = File.OpenRead(@"c:\platform.ini"))
                using (Stream fileStream = File.OpenRead("testfile.txt"))
                using (WebClient client = new WebClient())
                {
                    MultipartHelper helper = new MultipartHelper();
    
                    NameValueCollection props = new NameValueCollection();
                    props.Add("fname", "john");
                    props.Add("id", "acme");
                    helper.Add(new NameValuePart(props));
    
                    FilePart filepart = new FilePart(fileStream, "pics1", "text/plain");
                    filepart.FileName = "1.jpg";
                    helper.Add(filepart);
    
                    FilePart ini = new FilePart(iniStream, "pics2", "text/plain");
                    ini.FileName = "inifile.ini";
                    helper.Add(ini);
    
                    helper.Upload(client, "http://localhost/form.aspx", "POST");
                }
            }
            catch (Exception e)
            {
                Trace.WriteLine(e);
            }
        }
    }
    

    This will work with all versions of the .NET framework.

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

    something like this is close: (untested code)

    byte[] data; // data goes here.
    
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Credentials = userNetworkCredentials;
    request.Method = "PUT";
    request.ContentType = "application/octet-stream";
    request.ContentLength = data.Length;
    Stream stream = request.GetRequestStream();
    stream.Write(data,0,data.Length);
    stream.Close();
    response = (HttpWebResponse)request.GetResponse();
    StreamReader reader = new StreamReader(response.GetResponseStream());
    temp = reader.ReadToEnd();
    reader.Close();
    
    0 讨论(0)
提交回复
热议问题