之前对接一个接口,实现加密文件上传,于是写了一个简单的方法进行调用。
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#简单实现HTTP文件上传