使用HTTPWebrequest(multipart / form-data)上传文件

是否有任何类,库或代码将帮助我上传HTTPWebrequest的文件?

编辑2:

我不想上传到WebDAV文件夹或类似的东西。 我想模拟一个浏览器,所以就像你上传你的头像到论坛或通过Web应用程序中的表单上传文件。 上传到使用多部分/表单数据的表单。

编辑:

WebClient不包括我的要求,所以我正在寻找HTTPWebrequest解决scheme。

20 Solutions collect form web for “使用HTTPWebrequest(multipart / form-data)上传文件”

采取了上面的代码和固定,因为它会引发内部服务器错误500. \ r \ n定位和空间不足等问题。应用与内存stream的重构,直接写入请求stream。 结果如下:

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: // <form action="{url}" method="post" enctype="multipart/form-data"> // <input type="text" name="filename" /> // <input type="file" name="file1" /> // <input type="file" name="file2" /> // </form> private System.IO.Stream Upload(string url, string filename, Stream fileStream, byte [] fileBytes) { // Convert each of the three inputs into HttpContent objects HttpContent stringContent = new StringContent(filename); // examples of converting both Stream and byte [] to HttpContent objects // representing input type file HttpContent fileStreamContent = new StreamContent(fileStream); HttpContent bytesContent = new ByteArrayContent(fileBytes); // Submit the form using HttpClient and // create form data as Multipart (enctype="multipart/form-data") using (var client = new HttpClient()) using (var formData = new MultipartFormDataContent()) { // Add the HttpContent objects to the form data // <input type="text" name="filename" /> formData.Add(stringContent, "filename", "filename"); // <input type="file" name="file1" /> formData.Add(fileStreamContent, "file1", "file1"); // <input type="file" name="file2" /> formData.Add(bytesContent, "file2", "file2"); // Invoke the request to the server // equivalent to pressing the submit button on // a form with attributes (action="{url}" method="post") var response = client.PostAsync(url, formData).Result; // ensure the request was a success if (!response.IsSuccessStatusCode) { return null; } return response.Content.ReadAsStreamAsync().Result; } } 

我的ASP.NET上传常见问题有一个关于这个的文章,例子代码: 使用HttpWebRequest / WebClient使用RFC 1867 POST请求上传文件 。 此代码不会将文件加载到内存中(与上面的代码相对),支持多个文件,并支持表单值,设置凭据和Cookie等

编辑:看起来像Axosoft拿下了页面。 多谢你们。

它仍然可以通过archive.org访问。

根据上面提供的代码,我添加了对多个文件的支持,并且直接上传了一个stream,而不需要本地文件。

要将file upload到特定的url(包括一些后参数),请执行以下操作:

 RequestHelper.PostMultipart( "http://www.myserver.com/upload.php", new Dictionary<string, object>() { { "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 } }, }); 

为了增强这一点,甚至可以从给定的文件本身确定名称和MIMEtypes。

 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, Dictionary<string, object> parameters) { 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<string, object> 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(); } } } 

像这样的东西是密切的:(未经testing的代码)

 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<file.Count();i++) { header = string.Format(headerTemplate, paramName[i], System.IO.Path.GetFileName(file[i]), contentType[i]); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); rs.Write(headerbytes, 0, headerbytes.Length); FileStream fileStream = new FileStream(file[i], 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(); rs.Write(boundarybytes, 0, boundarybytes.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); wresp.Close(); wresp = null; } finally { wr = null; } } 

我想你正在寻找更像WebClient的东西。

具体来说, UploadFile() 。

VB示例(从另一个post上的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 

最近我不得不处理这个问题 – 另一种方法是使用WebClient是可inheritance的,并从这里改变底层的WebRequest:

http://msdn.microsoft.com/en-us/library/system.net.webclient.getwebrequest(VS.80).aspx

我更喜欢C#,但是如果你被困在VB中,结果将如下所示:

 Public Class BigWebClient Inherits WebClient Protected Overrides Function GetWebRequest(ByVal address As System.Uri) As System.Net.WebRequest Dim x As WebRequest = MyBase.GetWebRequest(address) x.Timeout = 60 * 60 * 1000 Return x End Function End Class 'Use BigWebClient here instead of WebClient 

还有一个工作的例子,我的一些评论:

  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! 

我正在寻找file upload,并在VB.NET中添加一些参数到multipart / form-data请求,而不是通过常规的表单发布。 感谢@JoshCodes答案我得到了我正在寻找的方向。 我张贴我的解决scheme,以帮助他人find一种方式来执行文件和参数的职位,我试图实现的HTML等价物是:html

 <form action="your-api-endpoint" enctype="multipart/form-data" method="post"> <input type="hidden" name="action" value="api-method-name"/> <input type="hidden" name="apiKey" value="gs1xxxxxxxxxxxxxex"/> <input type="hidden" name="access" value="protected"/> <input type="hidden" name="name" value="test"/> <input type="hidden" name="title" value="test"/> <input type="hidden" name="signature" value="cf1d4xxxxxxxxcd5"/> <input type="file" name="file"/> <input type="submit" name="_upload" value="Upload"/> </form> 

由于我必须提供apiKey和签名(这是请求参数和api键串联string的计算校验和),所以我需要在服务器端进行。 我需要做服务器端的另一个原因是文件的post可以在任何时候通过指向已经在服务器上的文件(提供path)来执行,所以在表单中将不存在手动select的文件因此表单数据文件不会包含文件stream。否则,我可以通过ajaxcallback来计算校验和,并使用JQuery通过html文件提交文件。 我正在使用.net版本4.0,并且不能在实际解决scheme中升级到4.5。 所以我不得不使用nuget cmd安装Microsoft.Net.Http

 PM> install-package Microsoft.Net.Http Private Function UploadFile(req As ApiRequest, filePath As String, fileName As String) As String Dim result = String.empty Try ''//Get file stream Dim paramFileStream As Stream = File.OpenRead(filePath) Dim fileStreamContent As HttpContent = New StreamContent(paramFileStream) Using client = New HttpClient() Using formData = New MultipartFormDataContent() ''// This adds parameter name ("action") ''// parameter value (req.Action) to form data formData.Add(New StringContent(req.Action), "action") formData.Add(New StringContent(req.ApiKey), "apiKey") For Each param In req.Parameters formData.Add(New StringContent(param.Value), param.Key) Next formData.Add(New StringContent(req.getRequestSignature.Qualifier), "signature") ''//This adds the file stream and file info to form data formData.Add(fileStreamContent, "file", fileName) ''//We are now sending the request Dim response = client.PostAsync(GetAPIEndpoint(), formData).Result ''//We are here reading the response Dim readR = New StreamReader(response.Content.ReadAsStreamAsync().Result, Encoding.UTF8) Dim respContent = readR.ReadToEnd() If Not response.IsSuccessStatusCode Then result = "Request Failed : Code = " & response.StatusCode & "Reason = " & response.ReasonPhrase & "Message = " & respContent End If result.Value = respContent End Using End Using Catch ex As Exception result = "An error occurred : " & ex.Message End Try Return result End Function 

不知道这是否发布之前,但我得到了与WebClient的工作。 我阅读WebClient的文档。 他们提出的一个关键点是

如果BaseAddress属性不是空string(“”),并且地址不包含绝对URI,则地址必须是与BaseAddress组合的相对URI,以形成请求数据的绝对URI。 如果QueryString属性不是一个空string,它将被追加到地址。

所以我所做的只是wc.QueryString.Add(“source”,generatedImage)添加不同的查询参数,并以某种方式匹配属性名称与我上传的图像。 希望它有帮助

  public void postImageToFacebook(string generatedImage, string fbGraphUrl) { WebClient wc = new WebClient(); byte[] bytes = System.IO.File.ReadAllBytes(generatedImage); wc.QueryString.Add("source", generatedImage); wc.QueryString.Add("message", "helloworld"); wc.UploadFile(fbGraphUrl, generatedImage); wc.Dispose(); } 

修改@CristianRomanescu代码来处理内存stream,接受文件作为字节数组,允许空的nvc,返回请求响应,并与授权标题一起使用。 用Web Api 2testing代码。

 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(); } } 

我永远不能得到的例子正常工作,我总是收到500错误发送到服务器时。

然而,我遇到了一个非常优雅的方法,在这个url做到这一点

它很容易扩展,显然可以用二进制文件和XML工作。

你用类似的方式来调用它

 class Program { public static string gsaFeedURL = "http://yourGSA.domain.com:19900/xmlfeed"; static void Main() { try { postWebData(); } catch (Exception ex) { } } // new one I made from C# web service public static void postWebData() { StringDictionary dictionary = new StringDictionary(); UploadSpec uploadSpecs = new UploadSpec(); UTF8Encoding encoding = new UTF8Encoding(); byte[] bytes; Uri gsaURI = new Uri(gsaFeedURL); // Create new URI to GSA feeder gate string sourceURL = @"C:\FeedFile.xml"; // Location of the XML feed file // Two parameters to send string feedtype = "full"; string datasource = "test"; try { // Add the parameter values to the dictionary dictionary.Add("feedtype", feedtype); dictionary.Add("datasource", datasource); // Load the feed file created and get its bytes XmlDocument xml = new XmlDocument(); xml.Load(sourceURL); bytes = Encoding.UTF8.GetBytes(xml.OuterXml); // Add data to upload specs uploadSpecs.Contents = bytes; uploadSpecs.FileName = sourceURL; uploadSpecs.FieldName = "data"; // Post the data if ((int)HttpUpload.Upload(gsaURI, dictionary, uploadSpecs).StatusCode == 200) { Console.WriteLine("Successful."); } else { // GSA POST not successful Console.WriteLine("Failure."); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } 

对于我来说,下面的作品(主要是从以下所有答案中吸取的),我从Elad的答案开始,修改/简化与我的需要相匹配的东西(删除不是文件格式input,只有一个文件…)。

希望它可以帮助某人:)

(PS:我知道exception处理没有执行,并假定它是写在一个类里,所以我可能需要一些集成工作…)

 private void uploadFile() { Random rand = new Random(); string boundary = "----boundary" + rand.Next().ToString(); Stream data_stream; byte[] header = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"file_path\"; filename=\"" + System.IO.Path.GetFileName(this.file) + "\"\r\nContent-Type: application/octet-stream\r\n\r\n"); byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); // Do the request HttpWebRequest request = (HttpWebRequest)WebRequest.Create(MBF_URL); request.UserAgent = "My Toolbox"; request.Method = "POST"; request.KeepAlive = true; request.ContentType = "multipart/form-data; boundary=" + boundary; data_stream = request.GetRequestStream(); data_stream.Write(header, 0, header.Length); byte[] file_bytes = System.IO.File.ReadAllBytes(this.file); data_stream.Write(file_bytes, 0, file_bytes.Length); data_stream.Write(trailer, 0, trailer.Length); data_stream.Close(); // Read the response WebResponse response = request.GetResponse(); data_stream = response.GetResponseStream(); StreamReader reader = new StreamReader(data_stream); this.url = reader.ReadToEnd(); if (this.url == "") { this.url = "No response :("; } reader.Close(); data_stream.Close(); response.Close(); } 

Check out the MyToolkit library:

 var request = new HttpPostRequest("http://www.server.com"); request.Data.Add("name", "value"); // POST data request.Files.Add(new HttpPostFile("name", "file.jpg", "path/to/file.jpg")); await Http.PostAsync(request, OnRequestFinished); 

http://mytoolkit.codeplex.com/wikipage?title=Http

I wrote a class using WebClient way back when to do multipart form upload.

http://ferozedaud.blogspot.com/2010/03/multipart-form-upload-helper.html

 /// /// MimePart /// Abstract class for all MimeParts /// abstract class MimePart { public string Name { get; set; } public abstract string ContentDisposition { get; } public abstract string ContentType { get; } public abstract void CopyTo(Stream stream); public String Boundary { get; set; } } class NameValuePart : MimePart { private NameValueCollection nameValues; public NameValuePart(NameValueCollection nameValues) { this.nameValues = nameValues; } public override void CopyTo(Stream stream) { string boundary = this.Boundary; StringBuilder sb = new StringBuilder(); foreach (object element in this.nameValues.Keys) { sb.AppendFormat("--{0}", boundary); sb.Append("\r\n"); sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\";", element); sb.Append("\r\n"); sb.Append("\r\n"); sb.Append(this.nameValues[element.ToString()]); sb.Append("\r\n"); } sb.AppendFormat("--{0}", boundary); sb.Append("\r\n"); //Trace.WriteLine(sb.ToString()); byte [] data = Encoding.ASCII.GetBytes(sb.ToString()); stream.Write(data, 0, data.Length); } public override string ContentDisposition { get { return "form-data"; } } public override string ContentType { get { return String.Empty; } } } class FilePart : MimePart { private Stream input; private String contentType; public FilePart(Stream input, String name, String contentType) { this.input = input; this.contentType = contentType; this.Name = name; } public override void CopyTo(Stream stream) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("Content-Disposition: {0}", this.ContentDisposition); if (this.Name != null) sb.Append("; ").AppendFormat("name=\"{0}\"", this.Name); if (this.FileName != null) sb.Append("; ").AppendFormat("filename=\"{0}\"", this.FileName); sb.Append("\r\n"); sb.AppendFormat(this.ContentType); sb.Append("\r\n"); sb.Append("\r\n"); // serialize the header data. byte[] buffer = Encoding.ASCII.GetBytes(sb.ToString()); stream.Write(buffer, 0, buffer.Length); // send the stream. byte[] readBuffer = new byte[1024]; int read = input.Read(readBuffer, 0, readBuffer.Length); while (read > 0) { stream.Write(readBuffer, 0, read); read = input.Read(readBuffer, 0, readBuffer.Length); } // write the terminating boundary sb.Length = 0; sb.Append("\r\n"); sb.AppendFormat("--{0}", this.Boundary); sb.Append("\r\n"); buffer = Encoding.ASCII.GetBytes(sb.ToString()); stream.Write(buffer, 0, buffer.Length); } public override string ContentDisposition { get { return "file"; } } public override string ContentType { get { return String.Format("content-type: {0}", this.contentType); } } public String FileName { get; set; } } /// /// Helper class that encapsulates all file uploads /// in a mime part. /// class FilesCollection : MimePart { private List files; public FilesCollection() { this.files = new List(); this.Boundary = MultipartHelper.GetBoundary(); } public int Count { get { return this.files.Count; } } public override string ContentDisposition { get { return String.Format("form-data; name=\"{0}\"", this.Name); } } public override string ContentType { get { return String.Format("multipart/mixed; boundary={0}", this.Boundary); } } public override void CopyTo(Stream stream) { // serialize the headers StringBuilder sb = new StringBuilder(128); sb.Append("Content-Disposition: ").Append(this.ContentDisposition).Append("\r\n"); sb.Append("Content-Type: ").Append(this.ContentType).Append("\r\n"); sb.Append("\r\n"); sb.AppendFormat("--{0}", this.Boundary).Append("\r\n"); byte[] headerBytes = Encoding.ASCII.GetBytes(sb.ToString()); stream.Write(headerBytes, 0, headerBytes.Length); foreach (FilePart part in files) { part.Boundary = this.Boundary; part.CopyTo(stream); } } public void Add(FilePart part) { this.files.Add(part); } } /// /// Helper class to aid in uploading multipart /// entities to HTTP web endpoints. /// class MultipartHelper { private static Random random = new Random(Environment.TickCount); private List formData = new List(); private FilesCollection files = null; private MemoryStream bufferStream = new MemoryStream(); private string boundary; public String Boundary { get { return boundary; } } public static String GetBoundary() { return Environment.TickCount.ToString("X"); } public MultipartHelper() { this.boundary = MultipartHelper.GetBoundary(); } public void Add(NameValuePart part) { this.formData.Add(part); part.Boundary = boundary; } public void Add(FilePart part) { if (files == null) { files = new FilesCollection(); } this.files.Add(part); } public void Upload(WebClient client, string address, string method) { // set header client.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + this.boundary); Trace.WriteLine("Content-Type: multipart/form-data; boundary=" + this.boundary + "\r\n"); // first, serialize the form data foreach (NameValuePart part in this.formData) { part.CopyTo(bufferStream); } // serialize the files. this.files.CopyTo(bufferStream); if (this.files.Count > 0) { // add the terminating boundary. StringBuilder sb = new StringBuilder(); sb.AppendFormat("--{0}", this.Boundary).Append("\r\n"); byte [] buffer = Encoding.ASCII.GetBytes(sb.ToString()); bufferStream.Write(buffer, 0, buffer.Length); } bufferStream.Seek(0, SeekOrigin.Begin); Trace.WriteLine(Encoding.ASCII.GetString(bufferStream.ToArray())); byte [] response = client.UploadData(address, method, bufferStream.ToArray()); Trace.WriteLine("----- RESPONSE ------"); Trace.WriteLine(Encoding.ASCII.GetString(response)); } /// /// Helper class that encapsulates all file uploads /// in a mime part. /// class FilesCollection : MimePart { private List files; public FilesCollection() { this.files = new List(); this.Boundary = MultipartHelper.GetBoundary(); } public int Count { get { return this.files.Count; } } public override string ContentDisposition { get { return String.Format("form-data; name=\"{0}\"", this.Name); } } public override string ContentType { get { return String.Format("multipart/mixed; boundary={0}", this.Boundary); } } public override void CopyTo(Stream stream) { // serialize the headers StringBuilder sb = new StringBuilder(128); sb.Append("Content-Disposition: ").Append(this.ContentDisposition).Append("\r\n"); sb.Append("Content-Type: ").Append(this.ContentType).Append("\r\n"); sb.Append("\r\n"); sb.AppendFormat("--{0}", this.Boundary).Append("\r\n"); byte[] headerBytes = Encoding.ASCII.GetBytes(sb.ToString()); stream.Write(headerBytes, 0, headerBytes.Length); foreach (FilePart part in files) { part.Boundary = this.Boundary; part.CopyTo(stream); } } public void Add(FilePart part) { this.files.Add(part); } } } class Program { static void Main(string[] args) { Trace.Listeners.Add(new ConsoleTraceListener()); try { using (StreamWriter sw = new StreamWriter("testfile.txt", false)) { sw.Write("Hello there!"); } using (Stream iniStream = File.OpenRead(@"c:\platform.ini")) using (Stream fileStream = File.OpenRead("testfile.txt")) using (WebClient client = new WebClient()) { MultipartHelper helper = new MultipartHelper(); NameValueCollection props = new NameValueCollection(); props.Add("fname", "john"); props.Add("id", "acme"); helper.Add(new NameValuePart(props)); FilePart filepart = new FilePart(fileStream, "pics1", "text/plain"); filepart.FileName = "1.jpg"; helper.Add(filepart); FilePart ini = new FilePart(iniStream, "pics2", "text/plain"); ini.FileName = "inifile.ini"; helper.Add(ini); helper.Upload(client, "http://localhost/form.aspx", "POST"); } } catch (Exception e) { Trace.WriteLine(e); } } } 

This will work with all versions of the .NET framework.

Client use convert File to ToBase64String , after use Xml to promulgate to Server call, this server use File.WriteAllBytes(path,Convert.FromBase64String(dataFile_Client_sent)) .

Good lucky!

I realize this is probably really late, but I was searching for the same solution. I found the following response from a Microsoft rep

 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; } 
  • 从HttpWebRequest和HttpWebResponse获取Http状态代码(200,301,404等)
  • 如何将参数添加到WebRequest中?
  • 如何在C#中发送HTTPS GET请求
  • 是否可以将身份validation从Webbrowser传输到WebRequest
  • 获取使用HttpWebRequest / HttpWebResponse进行的HTTP请求和响应以显示在Fiddler中
  • 使用HttpWebRequest发布表单数据
  • 目标机器主动拒绝127.0.0.1:3446,因此无法build立连接
  • 在C#将匿名types转换为键/值数组?
  • 如何发布JSON到服务器?
  • 在C#中调整HttpWebRequest连接超时
  • C#HttpWebRequest与WebRequest