.NET WebClient和HttpWebRequest、HttpClient上传文件
在.NET中可以提供三种文件上传方式,WebClient和HttpWebRequest、HttpClient,在本文逐一示例演示,这个三个方式上传文件,要求开发者需要有一定的C#基础,初学者可能难以充分掌握,在阅读本文之前,要求已经知晓Form表单提交到服务端的原理,有过项目实践文件提交的基础。
WebClient
WebClient上传文件相对容易,它在System.Net.WebClient.dll中命名控件为System.Net,.NET FrameWork 2.0就可支持,提供了UploadFile和DowmloadFile等方法,上传下载文件可以用这个方法来操作。示例如下:
上面代码很简单通过两行完成了文件上传,把WebClient实例化声明一个myWebClient,然后使用UploadFile方法上传,在方法里面第一个参数即是上传文件接口地址“http://localhost:12526/FileApi.aspx”,本示例是传文件到当前项目;第二个传输方式POST或GET方式,在文件上传采用POST,如果简单数值参数提交也可用GET方式;第三个是本地图片地址,这里是D盘的1000.jpg。
接收文件则很简单,在FileApi.aspx的后台Page_Load中放入Request.Files接收文件,然后由HttpPostedFile保存,前台则留一行“<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FileApi.aspx.cs" Inherits="WebApplication4.FileApi" %>”即可,其它代码都不需要,这一行主要就是指定后台代码CodeBehind="FileApi.aspx.cs",如下:
下载文件则DownloadFile方法,方法两个参数:第一个是要下载目标网络Url地址路径,第二个则是保到存项的文件路径,这里是项目的Files文件夹中。目代码如下:
HttpWebRequest
HttpWebRequest上传文件,是模拟Form比表单提交数据,在html页面的Form表单中上传文件,由三个属性一个是action,用来提交文件指定的服务端页面,这里指定到当前项目的FileApi.aspx,action="FileApi.aspx";还有method属性设置,提交方式get或post,这里文件采用post,method="post";另一个则是上传文件必须指定的属性enctype="multipart/form-data"。下面是Html页面文件上传的Form表单代码:
下面我们通过Fidder检测文件上传的后台数据参数,在下图可以到Composer操作面板检测到的数据格式,上面是Post请求目标地址,发送的文件数据内容,Parsed选项面板RequestBody返回的数据格式,Raw可以查看图片转化成流后的编码内容。HttpWebRequest上传文件就是模拟的这个数据内容。
用(HttpWebRequest)WebRequest.Create(http://localhost:12526/FileApi.aspx) 建立连接,设定ContentType属性数据参数,设定Method为Post,Accept接收文件类型为*/*所有类型。
string file = @"D:\text.txt";//指定上传文件
string boundary = DateTime.Now.Ticks.ToString("x");//随机数
HttpWebRequest uploadRequest = (HttpWebRequest)WebRequest.Create("http://localhost:12526/FileApi.aspx");
uploadRequest.ContentType = "multipart/form-data; boundary=" + boundary;
uploadRequest.Method = "POST";
uploadRequest.Accept = "*/*";//文件类型
uploadRequest.KeepAlive = true; //否与 Internet 资源建立持续型连接,true为是,false为否
//设定好参数属性
/*.NET WebClient和HttpWebRequest、HttpClient上传文件(09.26.2020)
Copyright (C) 遗昕传媒 | weisim3.com*/
uploadRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
WebResponse reponse;
//创建一个内存流
Stream memStream = new MemoryStream();
//判断是否存在图片
FileInfo fileInfo = new FileInfo(file);
if (fileInfo.Exists)
{
boundary = "--" + boundary;//拼接
//上传文件参数格式边界
string paramFormat = boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}\r\n";
NameValueCollection param = new NameValueCollection();
param.Add("fname", Guid.NewGuid().ToString() + Path.GetExtension(file));
//写上参数
foreach (string key in param.Keys)
{
string formitem = string.Format(paramFormat, key, param[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
}
//上传文件数据格式边界
string dataFormat = boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\nContent-Type:application/octet-stream\r\n\r\n";
string header = string.Format(dataFormat, "Filedata", Path.GetFileName(file));
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
//获取文件内容
FileStream fileStream = new FileStream(file, 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);
}
fileStream.Close();
//string bd = "\r\n\n" + boundary + "\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\nSubmit Query\r\n" + boundary + "--";
//添加文件结束边界
byte[] boundarybytes = System.Text.Encoding.UTF8.GetBytes("\r\n\n" + boundary + "\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\nSubmit Query\r\n" + boundary + "--");
memStream.Write(boundarybytes, 0, boundarybytes.Length);
//请求长度
uploadRequest.ContentLength = memStream.Length;
//获取请求写入流
Stream requestStream = uploadRequest.GetRequestStream();
//将内存流数据读取位置归零
memStream.Position = 0;
byte[] tpBuffer = new byte[memStream.Length];
memStream.Read(tpBuffer, 0, tpBuffer.Length);
memStream.Close();
//将内存流中的buffer写入到请求写入流
requestStream.Write(tpBuffer, 0, tpBuffer.Length);
requestStream.Close();
//Response.Write(db);
}
HttpClient
HttpClient文件上传,这个方法被微软官方推荐的方法,在微软官方HttpWebRequest介绍中的建议“你不要将 HttpWebRequest 用于新的开发。 而应使用 System.Net.Http.HttpClient 类”。这个相对于HttpWebRequest更友好,HttpWebRequest对文件数据流拼接容易出错,开发效率要低。
protected void Page_Load(object sender, EventArgs e)
{
HttpClient client = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
HttpContent content = new StringContent("fileToUpload");
form.Add(content, "fileToUpload");
//下面是传参才需要
// HttpContent DictionaryItems = new FormUrlEncodedContent(parameters);
//form.Add(DictionaryItems, "medicineOrder");
var stream = new FileStream("d:\\java1.png", FileMode.Open);//拾取要上传的图片路径
content = new StreamContent(stream);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
//FileName是文件上传到服务器后的图片命名
Name = "fileToUpload",
FileName = "new.png"
};
form.Add(content);
HttpResponseMessage response = null;
try
{
response = (client.PostAsync("http://localhost:12526/FileApi.aspx", form)).Result;
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
三个方式上传文件,WebClient最容易,HttpWebRequest最繁琐只要模拟Form表单,进行文件流串码进行拼接是容易出错,HttpClient最友好提供全方位文件上传控制。
下载文件索引:
预知错误提示: 下载源码文件到本地后,需要就自己电脑机器上启动的localhost路径,“http://localhost:12526/FileApi.aspx”为当前示例在机器点电脑上的预览地址,下载到不同机器上会随机生成不同localhost地址,需要改成你自己的项目运行地址,否则报错。