在要求输入邮箱的文本域,请填写真实的邮件地址。非真实邮件地址,将收不到回复信息。

C#简单实现HTTP文件上传

C# 清风 463℃ 2评论

之前对接一个接口,实现加密文件上传,于是写了一个简单的方法进行调用。

    
 public static class HttpUtil
 {
        /// <summary>
        /// 向指定的URL进行post
        /// </summary>
        /// <param name="url"></param>
        /// <param name="bodyPartList"></param>
        /// <returns></returns>
        public static string MultipartPost(string url, List<FormBodyPart> bodyPartList
, bool isBrowerUserAgent = true)
        {
            if (string.IsNullOrEmpty(url) || bodyPartList == null || bodyPartList.Count == 0)
            {
                throw new Exception("参数缺失");
            }
            try
            {
                HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    if (url.ToLower().IndexOf("https", StringComparison.Ordinal) > -1)
                    {
                        ServicePointManager.ServerCertificateValidationCallback =
                            (sender, certificate, chain, errors) => true;
                    }
                }

                string userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36";
                if (!isBrowerUserAgent)
                {
                    userAgent = "Apache-HttpClient/4.3.4+";
                }
                webRequest.UserAgent = userAgent;
                webRequest.ContentType = $"multipart/form-data; boundary={bodyPartList[0].StrBoundary}";
                webRequest.Accept = "gzip,deflate";
                webRequest.Method = "POST";
                webRequest.KeepAlive = true;
                webRequest.ProtocolVersion = HttpVersion.Version10;

                long contentLength = 0;
                List postList = new List();
                foreach (FormBodyPart item in bodyPartList)
                {
                    byte[] tempData = item.GetBody();
                    postList.AddRange(tempData);
                    contentLength += tempData.Length;
                }
                byte[] boundaryBytes = Encoding.UTF8.GetBytes("--" + bodyPartList[0].StrBoundary + "--\r\n");
                postList.AddRange(boundaryBytes);
                webRequest.ContentLength = contentLength + boundaryBytes.Length;

                using (Stream stream = webRequest.GetRequestStream())
                {
                    byte[] postData = postList.ToArray();
                    stream.Write(postData, 0, postData.Length);
                }

                HttpWebResponse httpWeb = webRequest.GetResponse() as HttpWebResponse;
                StreamReader read = new StreamReader(httpWeb.GetResponseStream(), Encoding.UTF8);
                string resultMsg = read.ReadToEnd();

                read?.Close();
                read?.Dispose();
                webRequest?.Abort();
                httpWeb?.Close();
                httpWeb?.Dispose();

                return resultMsg;
            }
            catch (WebException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

    #region multipartPost Data Class
    public abstract class Multipart
    {
        private string name;
        private string strBoundary;
        private string fileName = "";
        private bool isFile = false;
        private long bodylength;

        protected string Name { get { return name; }  set { name = value; } }
        public string StrBoundary { get { return strBoundary = Boundary(); } }

        public abstract string ContentType { get; }
        protected string FileName { get { return fileName; } set { fileName = value; } }
        protected bool IsFile { get { return isFile; } set { isFile = value; } }
        public long Bodylength { get { return bodylength; } private set { bodylength = value; } }

        private string Boundary()
        {
            string strBoundary = "----WYJRFormBoundary";
            return $"{strBoundary}{Md5(strBoundary)}";
        }

        public void SetName(string name)
        {
            Name = name;
        }

        private string Md5(string key)
        {
            string md5 = "";
            System.Security.Cryptography.MD5 md5_text = System.Security.Cryptography.MD5.Create();
            byte[] temp = md5_text.ComputeHash(System.Text.Encoding.ASCII.GetBytes(key)); //计算MD5 Hash 值
            for (int i = 0; i < temp.Length; i++)
            {
                md5 += temp[i].ToString("x2");
            }
            return md5;
        }
        protected abstract byte[] GetBoundaryData();

        public byte[] GetBoundaryBody()
        {
            //请求头部信息 
            StringBuilder sbstr = new StringBuilder();
            sbstr.Append("--");
            sbstr.Append(StrBoundary);
            sbstr.Append("\r\n");
            sbstr.Append($"Content-Disposition: form-data; name=\"{Name}\"");
            if (IsFile)
            {
                sbstr.Append($"; filename=\"{FileName}\"");
            }
            if (!string.IsNullOrEmpty(ContentType))
            {
                sbstr.Append("\r\n");
                sbstr.Append("Content-Type: ");
                sbstr.Append(ContentType);
            }
            sbstr.Append("\r\n");
            sbstr.Append("\r\n");
            string strPostHeader = sbstr.ToString();

            byte[] postName = Encoding.UTF8.GetBytes(strPostHeader);
            //byte[] postName= Encoding.ASCII.GetBytes(strPostHeader);

            byte[] postData = GetBoundaryData();

            List postBoundaryData = new List();
            postBoundaryData.AddRange(postName);
            postBoundaryData.AddRange(postData);
            Bodylength = postName.Length + postData.Length;
            return postBoundaryData.ToArray();
        }

    }
    public class FileBody : Multipart
    {
        private FileInfo fileInfo;
        public FileBody(FileInfo file)
        {
            IsFile = true;
            fileInfo = file;
            FileName = file.Name;
        }
        public override string ContentType
        {
            get { return MimeMapping.GetMimeMapping(FileInfo.Name); }
        }

        public FileInfo FileInfo { get { return fileInfo; } }

        protected override byte[] GetBoundaryData()
        {
            List resultList = new List();
            byte[] newLine = Encoding.ASCII.GetBytes("\r\n");
            FileStream fs = fileInfo.OpenRead();
            byte[] fileContentByte = new byte[fs.Length]; // 二进制文件
            fs.Read(fileContentByte, 0, Convert.ToInt32(fs.Length));
            fs?.Close();
            fs?.Dispose();
            resultList.AddRange(fileContentByte);
            resultList.AddRange(newLine);
            return resultList.ToArray();
        }
    }

    public class StringBody : Multipart
    {
        private string dataVal;
        private string _contentType;
        public StringBody(string data, string contentType = "")
        {
            dataVal = data;
            _contentType = contentType;
        }

        public string DataVal { get { return dataVal; } }
        public override string ContentType { get { return _contentType; } }

        protected override byte[] GetBoundaryData()
        {
            string postBodymsg = $"{dataVal}\r\n";
            return Encoding.UTF8.GetBytes(postBodymsg);
            //return Encoding.ASCII.GetBytes(postBodymsg);
        }
    }

    public class FormBodyPart
    {
        private string name;
        Multipart multipart;
        private string strBoundary;
        private long bodyLength;
        public string Name { get { return name; } private set { name = value; } }
        public Multipart Multipart { get { return multipart; } private set { multipart = value; } }
        public string StrBoundary { get { return strBoundary; }
            private set { strBoundary = value; } }
        public long BodyLength { get { return bodyLength; } private set { bodyLength = value; } }

        public FormBodyPart(string name, Multipart postMultipart)
        {
            this.name = name;
            this.multipart = postMultipart;
            this.StrBoundary = multipart.StrBoundary;
        }

        public byte[] GetBody()
        {
            multipart.SetName(name);
            byte[] result = multipart.GetBoundaryBody();
            BodyLength = multipart.Bodylength;
            return result;
        }

    }
    #endregion

调用上传方法如下:

        
       static void Main(string[] args)
        {
            FileBody uploadFile = new FileBody(new FileInfo($"C:/1.zip"));
            FormBodyPart signCertPart = new FormBodyPart("sginCert", new StringBody("", "text/plain"));
            FormBodyPart usernamePart = new FormBodyPart("userName", new StringBody("", "text/plain"));
            FormBodyPart passwordPart = new FormBodyPart("password", new StringBody("", "text/plain"));
            FormBodyPart fileUploadPart = new FormBodyPart("uploadFile", uploadFile);  //文件上传
            FormBodyPart fileHashPart = new FormBodyPart("fileHash", new StringBody("", "text/plain"));
            FormBodyPart fileKeyPart = new FormBodyPart("fileKey", new StringBody("", "text/plain"));
            List<FormBodyPart> bodyPartList = new List<FormBodyPart>();
            bodyPartList.AddRange(new FormBodyPart[] { signCertPart, usernamePart, passwordPart, fileHashPart, fileKeyPart, fileUploadPart });

            string result = HttpUtil.MultipartPost("", bodyPartList);
            Console.WriteLine(result);
            Console.Read();
        }
代码实现中使用了MimeMapping类来获取文件Mime类型,此类在.NET Framework 4.5及以上版本中支持。如果使用的.NET Framework 版本在4.5以下,请查看以下链接获得处理方法。

C#获取文件的文件的MIME Type(Content-Type)的方法

转载请注明:清风博客 » C#简单实现HTTP文件上传

喜欢 (1)or分享 (0)
支付宝扫码打赏 微信打赏
发表我的评论
取消评论

CAPTCHA Image
Reload Image
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(2)个小伙伴在吐槽
  1. MimeMapping这个是啥啊?
    koalin2020-04-09 14:59 回复
    • 哎呀 !抱歉忘了这个问题了 !可以看下本站点另外一篇文章,就是这个东西。MimeMapping
      清风2020-04-09 15:17 回复