是否有任何类,库或一些代码可以帮助我使用HTTPWebrequest上传文件?
编辑2:
我不想上传到WebDAV文件夹或类似的东西.我想模拟浏览器,就像您将头像上传到论坛或通过Web应用程序中的表单上传文件一样.上传到使用multipart/form-data的表单.
编辑:
WebClient不能满足我的要求,所以我正在寻找HTTPWebrequest的解决方案.
取得上面的代码并修复,因为它会引发内部服务器错误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);
它可以扩展为处理多个文件,或者只为每个文件多次调用它.但它适合您的需求.
我正在寻找这样的东西,发现于:http: //bytes.com/groups/net-c/268661-how-upload-file-via-c-code(为正确性而修改):
public static string UploadFilesToRemoteUrl(string url, string[] files, NameValueCollection formFields = null) { string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); request.ContentType = "multipart/form-data; boundary=" + boundary; request.Method = "POST"; request.KeepAlive = true; Stream memStream = new System.IO.MemoryStream(); var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--"); string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; if (formFields != null) { foreach (string key in formFields.Keys) { string formitem = string.Format(formdataTemplate, key, formFields[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); memStream.Write(formitembytes, 0, formitembytes.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++) { memStream.Write(boundarybytes, 0, boundarybytes.Length); var header = string.Format(headerTemplate, "uplTheFile", files[i]); var headerbytes = System.Text.Encoding.UTF8.GetBytes(header); memStream.Write(headerbytes, 0, headerbytes.Length); using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read)) { var buffer = new byte[1024]; var bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { memStream.Write(buffer, 0, bytesRead); } } } memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); request.ContentLength = memStream.Length; using (Stream requestStream = request.GetRequestStream()) { memStream.Position = 0; byte[] tempBuffer = new byte[memStream.Length]; memStream.Read(tempBuffer, 0, tempBuffer.Length); memStream.Close(); requestStream.Write(tempBuffer, 0, tempBuffer.Length); } using (var response = request.GetResponse()) { Stream stream2 = response.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); return reader2.ReadToEnd(); } }
更新:使用.NET 4.5(或通过添加NuGet 的Microsoft.Net.Http软件包进行.NET 4.0 ),无需外部代码,扩展和"低级"HTTP操作即可实现.这是一个例子:
// Perform the equivalent of posting a form with a filename and two files, in HTML: //private async Task
我的ASP.NET上传常见问题解答中有一篇文章,其中包含示例代码:使用带有HttpWebRequest/WebClient的RFC 1867 POST请求上传文件.此代码不会将文件加载到内存中(与上面的代码相反),支持多个文件,并支持表单值,设置凭据和cookie等.
编辑:看起来像Axosoft取下页面.多谢你们.
它仍然可以通过archive.org访问.
根据上面提供的代码,我添加了对多个文件的支持,并且还可以直接上传流而无需拥有本地文件.
要将文件上传到包含一些邮政参数的特定网址,请执行以下操作:
RequestHelper.PostMultipart( "http://www.myserver.com/upload.php", new Dictionary() { { "testparam", "my value" }, { "file", new FormFile() { Name = "image.jpg", ContentType = "image/jpeg", FilePath = "c:\\temp\\myniceimage.jpg" } }, { "other_file", new FormFile() { Name = "image2.jpg", ContentType = "image/jpeg", Stream = imageDataStream } }, });
为了增强这一点,可以从给定文件本身确定名称和mime类型.
public class FormFile { public string Name { get; set; } public string ContentType { get; set; } public string FilePath { get; set; } public Stream Stream { get; set; } } public class RequestHelper { public static string PostMultipart(string url, Dictionaryparameters) { string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.ContentType = "multipart/form-data; boundary=" + boundary; request.Method = "POST"; request.KeepAlive = true; request.Credentials = System.Net.CredentialCache.DefaultCredentials; if(parameters != null && parameters.Count > 0) { using(Stream requestStream = request.GetRequestStream()) { foreach(KeyValuePair pair in parameters) { requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); if(pair.Value is FormFile) { FormFile file = pair.Value as FormFile; string header = "Content-Disposition: form-data; name=\"" + pair.Key + "\"; filename=\"" + file.Name + "\"\r\nContent-Type: " + file.ContentType + "\r\n\r\n"; byte[] bytes = System.Text.Encoding.UTF8.GetBytes(header); requestStream.Write(bytes, 0, bytes.Length); byte[] buffer = new byte[32768]; int bytesRead; if(file.Stream == null) { // upload from file using(FileStream fileStream = File.OpenRead(file.FilePath)) { while((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) requestStream.Write(buffer, 0, bytesRead); fileStream.Close(); } } else { // upload from given stream while((bytesRead = file.Stream.Read(buffer, 0, buffer.Length)) != 0) requestStream.Write(buffer, 0, bytesRead); } } else { string data = "Content-Disposition: form-data; name=\"" + pair.Key + "\"\r\n\r\n" + pair.Value; byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data); requestStream.Write(bytes, 0, bytes.Length); } } byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); requestStream.Write(trailer, 0, trailer.Length); requestStream.Close(); } } using(WebResponse response = request.GetResponse()) { using(Stream responseStream = response.GetResponseStream()) using(StreamReader reader = new StreamReader(responseStream)) return reader.ReadToEnd(); } } }
这样的事情很接近:(未经测试的代码)
byte[] data; // data goes here. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Credentials = userNetworkCredentials; request.Method = "PUT"; request.ContentType = "application/octet-stream"; request.ContentLength = data.Length; Stream stream = request.GetRequestStream(); stream.Write(data,0,data.Length); stream.Close(); response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); temp = reader.ReadToEnd(); reader.Close();
采取上述并修改它接受一些标头值和多个文件
NameValueCollection headers = new NameValueCollection(); headers.Add("Cookie", "name=value;"); headers.Add("Referer", "http://google.com"); NameValueCollection nvc = new NameValueCollection(); nvc.Add("name", "value"); HttpUploadFile(url, new string[] { "c:\\file1.txt", "c:\\file2.jpg" }, new string[] { "file", "image" }, new string[] { "application/octet-stream", "image/jpeg" }, nvc, headers);
public static void HttpUploadFile(string url, string[] file, string[] paramName, string[] contentType, NameValueCollection nvc, NameValueCollection headerItems) { //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); foreach (string key in headerItems.Keys) { if (key == "Referer") { wr.Referer = headerItems[key]; } else { wr.Headers.Add(key, headerItems[key]); } } 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 = ""; for(int i =0; i
8> John T..:我想你正在寻找更像WebClient的东西.
具体来说,UploadFile().
它应该是HTTPWebrequest,我知道WebClient,但这对这个项目没有好处.
9> Keith Walton..:VB示例(在另一篇文章中从C#示例转换):
Private Sub HttpUploadFile( _ ByVal uri As String, _ ByVal filePath As String, _ ByVal fileParameterName As String, _ ByVal contentType As String, _ ByVal otherParameters As Specialized.NameValueCollection) Dim boundary As String = "---------------------------" & DateTime.Now.Ticks.ToString("x") Dim newLine As String = System.Environment.NewLine Dim boundaryBytes As Byte() = Text.Encoding.ASCII.GetBytes(newLine & "--" & boundary & newLine) Dim request As Net.HttpWebRequest = Net.WebRequest.Create(uri) request.ContentType = "multipart/form-data; boundary=" & boundary request.Method = "POST" request.KeepAlive = True request.Credentials = Net.CredentialCache.DefaultCredentials Using requestStream As IO.Stream = request.GetRequestStream() Dim formDataTemplate As String = "Content-Disposition: form-data; name=""{0}""{1}{1}{2}" For Each key As String In otherParameters.Keys requestStream.Write(boundaryBytes, 0, boundaryBytes.Length) Dim formItem As String = String.Format(formDataTemplate, key, newLine, otherParameters(key)) Dim formItemBytes As Byte() = Text.Encoding.UTF8.GetBytes(formItem) requestStream.Write(formItemBytes, 0, formItemBytes.Length) Next key requestStream.Write(boundaryBytes, 0, boundaryBytes.Length) Dim headerTemplate As String = "Content-Disposition: form-data; name=""{0}""; filename=""{1}""{2}Content-Type: {3}{2}{2}" Dim header As String = String.Format(headerTemplate, fileParameterName, filePath, newLine, contentType) Dim headerBytes As Byte() = Text.Encoding.UTF8.GetBytes(header) requestStream.Write(headerBytes, 0, headerBytes.Length) Using fileStream As New IO.FileStream(filePath, IO.FileMode.Open, IO.FileAccess.Read) Dim buffer(4096) As Byte Dim bytesRead As Int32 = fileStream.Read(buffer, 0, buffer.Length) Do While (bytesRead > 0) requestStream.Write(buffer, 0, bytesRead) bytesRead = fileStream.Read(buffer, 0, buffer.Length) Loop End Using Dim trailer As Byte() = Text.Encoding.ASCII.GetBytes(newLine & "--" + boundary + "--" & newLine) requestStream.Write(trailer, 0, trailer.Length) End Using Dim response As Net.WebResponse = Nothing Try response = request.GetResponse() Using responseStream As IO.Stream = response.GetResponseStream() Using responseReader As New IO.StreamReader(responseStream) Dim responseText = responseReader.ReadToEnd() Diagnostics.Debug.Write(responseText) End Using End Using Catch exception As Net.WebException response = exception.Response If (response IsNot Nothing) Then Using reader As New IO.StreamReader(response.GetResponseStream()) Dim responseText = reader.ReadToEnd() Diagnostics.Debug.Write(responseText) End Using response.Close() End If Finally request = Nothing End Try End Sub