是否有任何类,库或一些代码片段,将帮助我上传文件与HTTPWebrequest?
编辑2:
我不想上传到WebDAV文件夹或类似的东西。我想模拟一个浏览器,就像你上传你的头像到一个论坛或通过一个web应用程序中的表单上传一个文件。上传到一个使用multipart/form-data的表单。
编辑:
WebClient不覆盖我的需求,所以我正在寻找一个解决方案与HTTPWebrequest。
是否有任何类,库或一些代码片段,将帮助我上传文件与HTTPWebrequest?
编辑2:
我不想上传到WebDAV文件夹或类似的东西。我想模拟一个浏览器,就像你上传你的头像到一个论坛或通过一个web应用程序中的表单上传一个文件。上传到一个使用multipart/form-data的表单。
编辑:
WebClient不覆盖我的需求,所以我正在寻找一个解决方案与HTTPWebrequest。
当前回答
修改了@CristianRomanescu代码,以使用内存流,接受文件作为字节数组,允许空nvc,返回请求响应和使用授权头。使用Web Api 2测试代码。
private string HttpUploadFile(string url, byte[] file, string fileName, string paramName, string contentType, NameValueCollection nvc, string authorizationHeader)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.Headers.Add("Authorization", authorizationHeader);
wr.KeepAlive = true;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
if (nvc != null)
{
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, fileName, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
rs.Write(file, 0, file.Length);
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
var response = reader2.ReadToEnd();
return response;
}
catch (Exception ex)
{
if (wresp != null)
{
wresp.Close();
wresp = null;
}
return null;
}
finally
{
wr = null;
}
}
Testcode:
[HttpPost]
[Route("postformdata")]
public IHttpActionResult PostFormData()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var provider = new MultipartMemoryStreamProvider();
try
{
// Read the form data.
var result = Request.Content.ReadAsMultipartAsync(provider).Result;
string response = "";
// This illustrates how to get the file names.
foreach (var file in provider.Contents)
{
var fileName = file.Headers.ContentDisposition.FileName.Trim('\"');
var buffer = file.ReadAsByteArrayAsync().Result;
response = HttpUploadFile("https://localhost/api/v1/createfromfile", buffer, fileName, "file", "application/pdf", null, "AuthorizationKey");
}
return Ok(response);
}
catch (System.Exception e)
{
return InternalServerError();
}
}
其他回答
我知道这可能有点晚了,但我一直在寻找同样的解决方案。我从一位微软代表那里找到了以下回复
private void UploadFilesToRemoteUrl(string url, string[] files, string logpath, NameValueCollection nvc)
{
long length = 0;
string boundary = "----------------------------" +
DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest2.ContentType = "multipart/form-data; boundary=" +
boundary;
httpWebRequest2.Method = "POST";
httpWebRequest2.KeepAlive = true;
httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream memStream = new System.IO.MemoryStream();
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
foreach(string key in nvc.Keys)
{
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
}
memStream.Write(boundarybytes,0,boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";
for(int i=0;i<files.Length;i++)
{
string header = string.Format(headerTemplate,"file"+i,files[i]);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes,0,headerbytes.Length);
FileStream fileStream = new FileStream(files[i], 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);
}
memStream.Write(boundarybytes,0,boundarybytes.Length);
fileStream.Close();
}
httpWebRequest2.ContentLength = memStream.Length;
Stream requestStream = httpWebRequest2.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer,0,tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer,0,tempBuffer.Length );
requestStream.Close();
WebResponse webResponse2 = httpWebRequest2.GetResponse();
Stream stream2 = webResponse2.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
webResponse2.Close();
httpWebRequest2 = null;
webResponse2 = null;
}
采用上面的代码并修复,因为它抛出内部服务器错误500。\r\n的位置和空格等存在一些问题。应用内存流重构,直接写入请求流。结果如下:
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {
log.Debug(string.Format("Uploading {0} to {1}", file, url));
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) {
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try {
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
} catch(Exception ex) {
log.Error("Error uploading file", ex);
if(wresp != null) {
wresp.Close();
wresp = null;
}
} finally {
wr = null;
}
}
以及示例用法:
NameValueCollection nvc = new NameValueCollection();
nvc.Add("id", "TTR");
nvc.Add("btn-submit-photo", "Upload");
HttpUploadFile("http://your.server.com/upload",
@"C:\test\test.jpg", "file", "image/jpeg", nvc);
可以扩展它来处理多个文件,或者对每个文件多次调用它。但它适合你的需要。
客户端使用转换文件到ToBase64String,使用Xml发布后 到服务器调用,这个服务器使用File.WriteAllBytes(path,Convert.FromBase64String(dataFile_Client_sent))。
好幸运!
这里有另一个我的评论的工作示例:
List<MimePart> mimeParts = new List<MimePart>();
try
{
foreach (string key in form.AllKeys)
{
StringMimePart part = new StringMimePart();
part.Headers["Content-Disposition"] = "form-data; name=\"" + key + "\"";
part.StringData = form[key];
mimeParts.Add(part);
}
int nameIndex = 0;
foreach (UploadFile file in files)
{
StreamMimePart part = new StreamMimePart();
if (string.IsNullOrEmpty(file.FieldName))
file.FieldName = "file" + nameIndex++;
part.Headers["Content-Disposition"] = "form-data; name=\"" + file.FieldName + "\"; filename=\"" + file.FileName + "\"";
part.Headers["Content-Type"] = file.ContentType;
part.SetStream(file.Data);
mimeParts.Add(part);
}
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
req.ContentType = "multipart/form-data; boundary=" + boundary;
req.Method = "POST";
long contentLength = 0;
byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");
foreach (MimePart part in mimeParts)
{
contentLength += part.GenerateHeaderFooterData(boundary);
}
req.ContentLength = contentLength + _footer.Length;
byte[] buffer = new byte[8192];
byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
int read;
using (Stream s = req.GetRequestStream())
{
foreach (MimePart part in mimeParts)
{
s.Write(part.Header, 0, part.Header.Length);
while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0)
s.Write(buffer, 0, read);
part.Data.Dispose();
s.Write(afterFile, 0, afterFile.Length);
}
s.Write(_footer, 0, _footer.Length);
}
return (HttpWebResponse)req.GetResponse();
}
catch
{
foreach (MimePart part in mimeParts)
if (part.Data != null)
part.Data.Dispose();
throw;
}
这里有一个使用的例子:
UploadFile[] files = new UploadFile[]
{
new UploadFile(@"C:\2.jpg","new_file","image/jpeg") //new_file is id of upload field
};
NameValueCollection form = new NameValueCollection();
form["id_hidden_input"] = "value_hidden_inpu"; //there is additional param (hidden fields on page)
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(full URL of action);
// set credentials/cookies etc.
req.CookieContainer = hrm.CookieContainer; //hrm is my class. i copied all cookies from last request to current (for auth)
HttpWebResponse resp = HttpUploadHelper.Upload(req, files, form);
using (Stream s = resp.GetResponseStream())
using (StreamReader sr = new StreamReader(s))
{
string response = sr.ReadToEnd();
}
//profit!
我想你在寻找更像WebClient的东西。
具体来说,还是()。