表单提交PostFormHelper

Web后台或Winform程序与其他系统对接时,经常用到HTTP/HTTPS的接口调用,且多为Post,我从网上搜到了相关代码,并在使用过程中补充了三个参数,PostFormHelper.cs如下

表单提交PostFormHelper
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace Common
{
    public static class FormUpload
    {
        private static readonly Encoding encoding = Encoding.UTF8;

        /// <summary>
        /// 提交表单
        /// </summary>
        /// <param name="postUrl"></param>
        /// <param name="userAgent"></param>
        /// <param name="postParameters"></param>
        /// <param name="waitResponse">是否等待回复</param>
        /// <param name="token">不需要tocken则为string.Empty</param>
        /// <param name="timeOut">超时时间(毫秒),0-使用默认100秒</param>
        /// <returns></returns>
        public static string MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters, bool waitResponse, string token = "", int timeOut = 0)
        {
            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, waitResponse, token, timeOut);
        }

        private static string PostForm(string postUrl, string userAgent, string contentType, byte[] formData, bool waitResponse, string token, int timeOut)
        {
            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";
            if (!string.IsNullOrEmpty(token)) request.Headers.Add("token", token);            
            request.ContentType = contentType;
            request.UserAgent = userAgent;
            request.CookieContainer = new CookieContainer();
            request.ContentLength = formData.Length;
            if (timeOut > 0) request.Timeout = timeOut;

            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(formData, 0, formData.Length);
                requestStream.Close();
            }

            if (waitResponse)
            {
                Stream instream = request.GetResponse().GetResponseStream();
                StreamReader sr = new StreamReader(instream, Encoding.UTF8);
                string response = sr.ReadToEnd();
                return response;
            }
            else return string.Empty;
        }

        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;
            }
        }
    }
}
View Code

调用示例如下

                string apiAddr = "http://{0}:80/v1/{1}";
                string userAgent = "Mozilla / 5.0(Windows NT 6.1; WOW64; Trident / 7.0; rv: 11.0) like Gecko";
                int timeOut = 1500;                

                Dictionary<string, object> postParams = new Dictionary<string, object>();
                postParams.Add("id", 1);
                postParams.Add("name", "John");
                postParams.Add("image", new FormUpload.FileParameter(File.ReadAllBytes(image),  "1.jpg"));
                string json = FormUpload.MultipartFormDataPost(apiAddr, userAgent, postParams, true, string.Empty, timeOut);     

如果出现“基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系”的异常,可添加如下代码

        ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);//验证服务器证书回调自动验证

        public static bool CheckValidationResult(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
    System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors errors)
        {   // 总是接受  
            return true;
        }
上一篇:利用FormData,实现上传图片的添加和删除功能


下一篇:上传文件到后端