سؤال

أحاول ملء نموذج في تطبيق php من عميل C# (Outlook addin).لقد استخدمت Fiddler لرؤية الطلب الأصلي من داخل تطبيق php ويتم إرسال النموذج كنموذج متعدد الأجزاء.لسوء الحظ، لا يأتي .Net مع دعم أصلي لهذا النوع من النماذج (WebClient لديه طريقة فقط لتحميل ملف).هل يعرف أحد مكتبة أو لديه بعض التعليمات البرمجية لتحقيق ذلك؟أرغب في نشر قيم مختلفة بالإضافة إلى ملف (ولكن في بعض الأحيان فقط).

شكرا لمساعدتك ، سيباستيان

هل كانت مفيدة؟

المحلول

ويتم قطع هذه ولصق من بعض نموذج التعليمات البرمجية كتبت، ونأمل ينبغي أن تعطي الأساسيات. ذلك يعتمد فقط بيانات الملف وبيانات النموذج في الوقت الراهن.

public class PostData
{

    private List<PostDataParam> m_Params;

    public List<PostDataParam> Params
    {
        get { return m_Params; }
        set { m_Params = value; }
    }

    public PostData()
    {
        m_Params = new List<PostDataParam>();

        // Add sample param
        m_Params.Add(new PostDataParam("email", "MyEmail", PostDataParamType.Field));
    }


    /// <summary>
    /// Returns the parameters array formatted for multi-part/form data
    /// </summary>
    /// <returns></returns>
    public string GetPostData()
    {
        // Get boundary, default is --AaB03x
        string boundary = ConfigurationManager.AppSettings["ContentBoundary"].ToString();

        StringBuilder sb = new StringBuilder();
        foreach (PostDataParam p in m_Params)
        {
            sb.AppendLine(boundary);

            if (p.Type == PostDataParamType.File)
            {
                sb.AppendLine(string.Format("Content-Disposition: file; name=\"{0}\"; filename=\"{1}\"", p.Name, p.FileName));
                sb.AppendLine("Content-Type: text/plain");
                sb.AppendLine();
                sb.AppendLine(p.Value);                 
            }
            else
            {
                sb.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"", p.Name));
                sb.AppendLine();
                sb.AppendLine(p.Value);
            }
        }

        sb.AppendLine(boundary);

        return sb.ToString();           
    }
}

public enum PostDataParamType
{
    Field,
    File
}

public class PostDataParam
{


    public PostDataParam(string name, string value, PostDataParamType type)
    {
        Name = name;
        Value = value;
        Type = type;
    }

    public string Name;
    public string FileName;
    public string Value;
    public PostDataParamType Type;
}

لإرسال البيانات ثم تحتاج إلى:

HttpWebRequest oRequest = null;
oRequest = (HttpWebRequest)HttpWebRequest.Create(oURL.URL);
oRequest.ContentType = "multipart/form-data";                       
oRequest.Method = "POST";
PostData pData = new PostData();

byte[] buffer = encoding.GetBytes(pData.GetPostData());

// Set content length of our data
oRequest.ContentLength = buffer.Length;

// Dump our buffered postdata to the stream, booyah
oStream = oRequest.GetRequestStream();
oStream.Write(buffer, 0, buffer.Length);
oStream.Close();

// get the response
oResponse = (HttpWebResponse)oRequest.GetResponse();

والأمل الذي يكون واضحا، لقد قص ولصق من مصادر قليلة للحصول على هذا أرتب.

نصائح أخرى

شكرا على الإجابات، الجميع!لقد اضطررت مؤخرًا إلى تنفيذ هذا الأمر، واستخدمت اقتراحاتك بكثافة.ومع ذلك، كان هناك بعض الأجزاء الصعبة التي لم تعمل كما هو متوقع، وكان معظمها يتعلق بتضمين الملف فعليًا (والذي كان جزءًا مهمًا من السؤال).هناك الكثير من الإجابات هنا بالفعل، ولكن أعتقد أن هذا قد يكون مفيدًا لشخص ما في المستقبل (لم أتمكن من العثور على العديد من الأمثلة الواضحة على ذلك عبر الإنترنت).أنا كتب تدوينة وهذا ما يفسر ذلك أكثر من ذلك بقليل.

في الأساس، حاولت أولاً تمرير بيانات الملف كسلسلة مشفرة بـ UTF8، ولكن كنت أواجه مشكلات في تشفير الملفات (كان يعمل بشكل جيد مع ملف نصي عادي، ولكن عند تحميل مستند Word، على سبيل المثال، إذا حاولت حفظه) الملف الذي تم تمريره إلى النموذج المنشور باستخدام Request.Files[0].SaveAs()، لم يعمل فتح الملف في Word بشكل صحيح.لقد وجدت أنه إذا كتبت بيانات الملف مباشرةً باستخدام Stream (بدلاً من StringBuilder)، فستعمل كما هو متوقع.بالإضافة إلى ذلك، قمت بإجراء بعض التعديلات التي جعلت الأمر أسهل بالنسبة لي للفهم.

بالمناسبة، نماذج متعددة الأجزاء تطلب التعليقات و ال توصية W3C لبيانات النموذج/الأجزاء المتعددة هناك بعض الموارد المفيدة في حالة احتياج أي شخص إلى مرجع للمواصفات.

لقد قمت بتغيير فئة WebHelpers لتكون أصغر قليلاً ولها واجهات أبسط، تسمى الآن FormUpload.إذا قمت بتمرير أ FormUpload.FileParameter يمكنك تمرير محتويات البايت [] مع اسم الملف ونوع المحتوى، وإذا قمت بتمرير سلسلة، فسيتم التعامل معها على أنها مجموعة قياسية من الاسم/القيمة.

هنا فئة FormUpload:

// Implements multipart/form-data POST in C# http://www.ietf.org/rfc/rfc2388.txt
// http://www.briangrinstead.com/blog/multipart-form-post-in-c
public static class FormUpload
{
    private static readonly Encoding encoding = Encoding.UTF8;
    public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters)
    {
        string formDataBoundary = String.Format("----------{0:N}", Guid.NewGuid());
        string contentType = "multipart/form-data; boundary=" + formDataBoundary;

        byte[] formData = GetMultipartFormData(postParameters, formDataBoundary);

        return PostForm(postUrl, userAgent, contentType, formData);
    }
    private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData)
    {
        HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest;

        if (request == null)
        {
            throw new NullReferenceException("request is not a http request");
        }

        // Set up the request properties.
        request.Method = "POST";
        request.ContentType = contentType;
        request.UserAgent = userAgent;
        request.CookieContainer = new CookieContainer();
        request.ContentLength = formData.Length;

        // You could add authentication here as well if needed:
        // request.PreAuthenticate = true;
        // request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
        // request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("username" + ":" + "password")));

        // Send the form data to the request.
        using (Stream requestStream = request.GetRequestStream())
        {
            requestStream.Write(formData, 0, formData.Length);
            requestStream.Close();
        }

        return request.GetResponse() as HttpWebResponse;
    }

    private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
    {
        Stream formDataStream = new System.IO.MemoryStream();
        bool needsCLRF = false;

        foreach (var param in postParameters)
        {
            // Thanks to feedback from commenters, add a CRLF to allow multiple parameters to be added.
            // Skip it on the first parameter, add it to subsequent parameters.
            if (needsCLRF)
                formDataStream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));

            needsCLRF = true;

            if (param.Value is FileParameter)
            {
                FileParameter fileToUpload = (FileParameter)param.Value;

                // Add just the first part of this param, since we will write the file data directly to the Stream
                string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
                    boundary,
                    param.Key,
                    fileToUpload.FileName ?? param.Key,
                    fileToUpload.ContentType ?? "application/octet-stream");

                formDataStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));

                // Write the file data directly to the Stream, rather than serializing it to a string.
                formDataStream.Write(fileToUpload.File, 0, fileToUpload.File.Length);
            }
            else
            {
                string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
                    boundary,
                    param.Key,
                    param.Value);
                formDataStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData));
            }
        }

        // Add the end of the request.  Start with a newline
        string footer = "\r\n--" + boundary + "--\r\n";
        formDataStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));

        // Dump the Stream into a byte[]
        formDataStream.Position = 0;
        byte[] formData = new byte[formDataStream.Length];
        formDataStream.Read(formData, 0, formData.Length);
        formDataStream.Close();

        return formData;
    }

    public class FileParameter
    {
        public byte[] File { get; set; }
        public string FileName { get; set; }
        public string ContentType { get; set; }
        public FileParameter(byte[] file) : this(file, null) { }
        public FileParameter(byte[] file, string filename) : this(file, filename, null) { }
        public FileParameter(byte[] file, string filename, string contenttype)
        {
            File = file;
            FileName = filename;
            ContentType = contenttype;
        }
    }
}

إليك رمز الاتصال الذي يقوم بتحميل ملف وبعض معلمات النشر العادية:

// Read file data
FileStream fs = new FileStream("c:\\people.doc", FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
fs.Close();

// Generate post objects
Dictionary<string, object> postParameters = new Dictionary<string, object>();
postParameters.Add("filename", "People.doc");
postParameters.Add("fileformat", "doc");
postParameters.Add("file", new FormUpload.FileParameter(data, "People.doc", "application/msword"));

// Create request and receive response
string postURL = "http://localhost";
string userAgent = "Someone";
HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters);

// Process response
StreamReader responseReader = new StreamReader(webResponse.GetResponseStream());
string fullResponse = responseReader.ReadToEnd();
webResponse.Close();
Response.Write(fullResponse);

ومع صافي 4.5 أنت حاليا يمكن استخدام System.Net.Http مساحة الاسم. فيما يلي مثال لتحميل ملف واحد باستخدام بيانات النموذج متعدد الأجزاء.

using System;
using System.IO;
using System.Net.Http;

namespace HttpClientTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new HttpClient();
            var content = new MultipartFormDataContent();
            content.Add(new StreamContent(File.Open("../../Image1.png", FileMode.Open)), "Image", "Image.png");
            content.Add(new StringContent("Place string content here"), "Content-Id in the HTTP"); 
            var result = client.PostAsync("https://hostname/api/Account/UploadAvatar", content);
            Console.WriteLine(result.Result.ToString());
        }
    }
}

وبناء على dnolans سبيل المثال، وهذا هو الإصدار الأول يمكن في الواقع الحصول على العمل (كانت هناك بعض الأخطاء مع الحدود، لم يتم تعيين الترميز): -)

لإرسال البيانات:

HttpWebRequest oRequest = null;
oRequest = (HttpWebRequest)HttpWebRequest.Create("http://you.url.here");
oRequest.ContentType = "multipart/form-data; boundary=" + PostData.boundary;
oRequest.Method = "POST";
PostData pData = new PostData();
Encoding encoding = Encoding.UTF8;
Stream oStream = null;

/* ... set the parameters, read files, etc. IE:
   pData.Params.Add(new PostDataParam("email", "example@example.com", PostDataParamType.Field));
   pData.Params.Add(new PostDataParam("fileupload", "filename.txt", "filecontents" PostDataParamType.File));
*/

byte[] buffer = encoding.GetBytes(pData.GetPostData());

oRequest.ContentLength = buffer.Length;

oStream = oRequest.GetRequestStream();
oStream.Write(buffer, 0, buffer.Length);
oStream.Close();

HttpWebResponse oResponse = (HttpWebResponse)oRequest.GetResponse();

والطبقة POSTDATA يجب أن تبدو:

public class PostData
{
    // Change this if you need to, not necessary
    public static string boundary = "AaB03x";

    private List<PostDataParam> m_Params;

    public List<PostDataParam> Params
    {
        get { return m_Params; }
        set { m_Params = value; }
    }

    public PostData()
    {
        m_Params = new List<PostDataParam>();
    }

    /// <summary>
    /// Returns the parameters array formatted for multi-part/form data
    /// </summary>
    /// <returns></returns>
    public string GetPostData()
    {
        StringBuilder sb = new StringBuilder();
        foreach (PostDataParam p in m_Params)
        {
            sb.AppendLine("--" + boundary);

            if (p.Type == PostDataParamType.File)
            {
                sb.AppendLine(string.Format("Content-Disposition: file; name=\"{0}\"; filename=\"{1}\"", p.Name, p.FileName));
                sb.AppendLine("Content-Type: application/octet-stream");
                sb.AppendLine();
                sb.AppendLine(p.Value);
            }
            else
            {
                sb.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"", p.Name));
                sb.AppendLine();
                sb.AppendLine(p.Value);
            }
        }

        sb.AppendLine("--" + boundary + "--");

        return sb.ToString();
    }
}

public enum PostDataParamType
{
    Field,
    File
}

public class PostDataParam
{
    public PostDataParam(string name, string value, PostDataParamType type)
    {
        Name = name;
        Value = value;
        Type = type;
    }

    public PostDataParam(string name, string filename, string value, PostDataParamType type)
    {
        Name = name;
        Value = value;
        FileName = filename;
        Type = type;
    }

    public string Name;
    public string FileName;
    public string Value;
    public PostDataParamType Type;
}

في إصدار. NET أستخدمه لديك أيضا للقيام بذلك:

System.Net.ServicePointManager.Expect100Continue = false;

إذا لم تقم بذلك، الطبقة HttpWebRequest سوف تضاف تلقائيا في Expect:100-continue طلب رأس الذي يلوث كل شيء.

وأيضا تعلمت بالطريقة الصعبة أن يكون لديك العدد الصحيح من شرطات. كل ما تقوله هو "الحدود" في رأس Content-Type يجب أن يسبقه شرطتين

--THEBOUNDARY

وفي نهاية

--THEBOUNDARY--

وتماما كما هو الحال في المثال التعليمات البرمجية. إذا الحد الخاص بك هو الكثير من شرطات متبوعا برقم فإن هذا الخطأ لا يكون واضحا من خلال النظر في طلب HTTP في ملقم وكيل

وشكرا لرمز، أنها وفرت لي الكثير من الوقت (بما في ذلك الخطأ Except100!).

وعلى أي حال، لقد وجدت خطأ في رمز، هنا:

formDataStream.Write(encoding.GetBytes(postData), 0, postData.Length);

في حالة البيانات وظيفة الخاص بك هو UTF-16، postData.Length، سيعود عدد من الشخصيات وليس عدد بايت. وهذا اقتطاع البيانات التي يجري نشرها (على سبيل المثال، إذا كان لديك 2 حرف التي يتم ترميز ك UTF-16، وأنها تأخذ 4 بايت، ولكن سوف أقول postData.Length يستغرق 2 بايت، وتفقد وحدات البايت النهائية للنشر 2 البيانات).

والحل - استبدال هذا الخط مع:

byte[] aPostData=encoding.GetBytes(postData);
formDataStream.Write(aPostData, 0, aPostData.Length);

وباستخدام هذا، ويتم احتساب طول حسب حجم البايت []، وليس حجم السلسلة.

والتحسين القليل من الطبقة قبل. في هذا الإصدار لا يتم تحميل الملفات تماما في الذاكرة.

استشارات الأمن: شيك للحدود مفقود، إذا كان الملف يحتوي على bounday أنه سوف تعطل

namespace WindowsFormsApplication1
{
    public static class FormUpload
    {
        private static string NewDataBoundary()
        {
            Random rnd = new Random();
            string formDataBoundary = "";
            while (formDataBoundary.Length < 15)
            {
                formDataBoundary = formDataBoundary + rnd.Next();
            }
            formDataBoundary = formDataBoundary.Substring(0, 15);
            formDataBoundary = "-----------------------------" + formDataBoundary;
            return formDataBoundary;
        }

        public static HttpWebResponse MultipartFormDataPost(string postUrl, IEnumerable<Cookie> cookies, Dictionary<string, string> postParameters)
        {
            string boundary = NewDataBoundary();

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUrl);

            // Set up the request properties
            request.Method = "POST";
            request.ContentType = "multipart/form-data; boundary=" + boundary;
            request.UserAgent = "PhasDocAgent 1.0";
            request.CookieContainer = new CookieContainer();

            foreach (var cookie in cookies)
            {
                request.CookieContainer.Add(cookie);
            }

            #region WRITING STREAM
            using (Stream formDataStream = request.GetRequestStream())
            {
                foreach (var param in postParameters)
                {
                    if (param.Value.StartsWith("file://"))
                    {
                        string filepath = param.Value.Substring(7);

                        // Add just the first part of this param, since we will write the file data directly to the Stream
                        string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
                            boundary,
                            param.Key,
                            Path.GetFileName(filepath) ?? param.Key,
                            MimeTypes.GetMime(filepath));

                        formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, header.Length);

                        // Write the file data directly to the Stream, rather than serializing it to a string.

                        byte[] buffer = new byte[2048];

                        FileStream fs = new FileStream(filepath, FileMode.Open);

                        for (int i = 0; i < fs.Length; )
                        {
                            int k = fs.Read(buffer, 0, buffer.Length);
                            if (k > 0)
                            {
                                formDataStream.Write(buffer, 0, k);
                            }
                            i = i + k;
                        }
                        fs.Close();
                    }
                    else
                    {
                        string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n",
                            boundary,
                            param.Key,
                            param.Value);
                        formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, postData.Length);
                    }
                }
                // Add the end of the request
                byte[] footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
                formDataStream.Write(footer, 0, footer.Length);
                request.ContentLength = formDataStream.Length;
                formDataStream.Close();
            }
            #endregion

            return request.GetResponse() as HttpWebResponse;
        }
    }
}

وأنا في حاجة لمحاكاة تسجيل الدخول المتصفح لموقع على شبكة الانترنت للحصول على الكعكة تسجيل الدخول، وكان نموذج تسجيل الدخول متعددة / بيانات النموذج.

وأخذت بعض أدلة من الأجوبة الأخرى هنا، وبعد ذلك حاول الحصول على بلدي السيناريو الخاص تعمل. استغرق الأمر قليلا من التجربة المحبطة والخطأ قبل أن يعمل الحق، ولكن هنا هو رمز:

    public static class WebHelpers
    {
        /// <summary>
        /// Post the data as a multipart form
        /// </summary>
       public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, string> values)
       {
           string formDataBoundary = "---------------------------" + WebHelpers.RandomHexDigits(12);
           string contentType = "multipart/form-data; boundary=" + formDataBoundary;

           string formData = WebHelpers.MakeMultipartForm(values, formDataBoundary);
           return WebHelpers.PostForm(postUrl, userAgent, contentType, formData);
       }

        /// <summary>
        /// Post a form
        /// </summary>
        public static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, string formData)
        {
            HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest;

            if (request == null)
            {
                throw new NullReferenceException("request is not a http request");
            }

            // Add these, as we're doing a POST
            request.Method = "POST";
            request.ContentType = contentType;
            request.UserAgent = userAgent;
            request.CookieContainer = new CookieContainer();

            // We need to count how many bytes we're sending. 
            byte[] postBytes = Encoding.UTF8.GetBytes(formData);
            request.ContentLength = postBytes.Length;

            using (Stream requestStream = request.GetRequestStream())
            {
                // Push it out there
                requestStream.Write(postBytes, 0, postBytes.Length);
                requestStream.Close();
            }

            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>
        /// Generate random hex digits 
        /// </summary>
        public static string RandomHexDigits(int count)
        {
            Random random = new Random();
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < count; i++)
            {
                int digit = random.Next(16);
                result.AppendFormat("{0:x}", digit);
            }

            return result.ToString();
        }

        /// <summary>
        /// Turn the key and value pairs into a multipart form
        /// </summary>
        private static string MakeMultipartForm(Dictionary<string, string> values, string boundary)
        {
            StringBuilder sb = new StringBuilder();

            foreach (var pair in values)
            {
                sb.AppendFormat("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", boundary, pair.Key, pair.Value);
            }

            sb.AppendFormat("--{0}--\r\n", boundary);

            return sb.ToString();    
        }
    }
}

وانها لا تعامل مع ملف البيانات، تشكل فقط لأن هذا هو كل ما احتاجه. دعوت مثل هذا:

    try
    {
        using (HttpWebResponse response = WebHelpers.MultipartFormDataPost(postUrl, UserAgentString, this.loginForm)) 
        {
            if (response != null)
            {
                Cookie loginCookie = response.Cookies["logincookie"];
                .....

وفيما يلي التعليمات البرمجية التي أنا باستخدام

    //This URL not exist, it's only an example.
    string url = "http://myBox.s3.amazonaws.com/";
    //Instantiate new CustomWebRequest class
    CustomWebRequest wr = new CustomWebRequest(url);
    //Set values for parameters
    wr.ParamsCollection.Add(new ParamsStruct("key", "${filename}"));
    wr.ParamsCollection.Add(new ParamsStruct("acl", "public-read"));
    wr.ParamsCollection.Add(new ParamsStruct("success_action_redirect", "http://www.yahoo.com"));
    wr.ParamsCollection.Add(new ParamsStruct("x-amz-meta-uuid", "14365123651274"));
    wr.ParamsCollection.Add(new ParamsStruct("x-amz-meta-tag", ""));
    wr.ParamsCollection.Add(new ParamsStruct("AWSAccessKeyId", "zzzz"));            
    wr.ParamsCollection.Add(new ParamsStruct("Policy", "adsfadsf"));
    wr.ParamsCollection.Add(new ParamsStruct("Signature", "hH6lK6cA="));
    //For file type, send the inputstream of selected file
    StreamReader sr = new StreamReader(@"file.txt");
    wr.ParamsCollection.Add(new ParamsStruct("file", sr, ParamsStruct.ParamType.File, "file.txt"));

    wr.PostData();

ومن الرابط التالي لقد قمت بتحميل نفس الرمز http://www.codeproject.com/KB/cs/multipart_request_C_.aspx

وأي مساعدة

وبلدي تنفيذ

/// <summary>
/// Sending file via multipart\form-data
/// </summary>
/// <param name="url">URL for send</param>
/// <param name="file">Local file path</param>
/// <param name="paramName">Request file param</param>
/// <param name="contentType">Content-Type file headr</param>
/// <param name="nvc">Additional post params</param>
private static string httpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
    //delimeter
    var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");

    //creating request
    var wr = (HttpWebRequest)WebRequest.Create(url);
    wr.ContentType = "multipart/form-data; boundary=" + boundary;
    wr.Method = "POST";
    wr.KeepAlive = true;

    //sending request
    using(var requestStream = wr.GetRequestStream())
    {
        using (var requestWriter = new StreamWriter(requestStream, Encoding.UTF8))
        {
            //params
            const string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
            foreach (string key in nvc.Keys)
            {
                requestWriter.Write(boundary);
                requestWriter.Write(String.Format(formdataTemplate, key, nvc[key]));
            }
            requestWriter.Write(boundary);

            //file header
            const string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
            requestWriter.Write(String.Format(headerTemplate, paramName, file, contentType));

            //file content
            using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                fileStream.CopyTo(requestStream);
            }

            requestWriter.Write("\r\n--" + boundary + "--\r\n");
        }
    }

    //reading response
    try
    {
        using (var wresp = (HttpWebResponse)wr.GetResponse())
        {
            if (wresp.StatusCode == HttpStatusCode.OK)
            {
                using (var responseStream = wresp.GetResponseStream())
                {
                    if (responseStream == null)
                        return null;
                    using (var responseReader = new StreamReader(responseStream))
                    {
                        return responseReader.ReadToEnd();
                    }
                }
            }

            throw new ApplicationException("Error while upload files. Server status code: " + wresp.StatusCode.ToString());
        }
    }
    catch (Exception ex)
    {
        throw new ApplicationException("Error while uploading file", ex);
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top