是否有任何类,库或一些代码片段,将帮助我上传文件与HTTPWebrequest?
编辑2:
我不想上传到WebDAV文件夹或类似的东西。我想模拟一个浏览器,就像你上传你的头像到一个论坛或通过一个web应用程序中的表单上传一个文件。上传到一个使用multipart/form-data的表单。
编辑:
WebClient不覆盖我的需求,所以我正在寻找一个解决方案与HTTPWebrequest。
是否有任何类,库或一些代码片段,将帮助我上传文件与HTTPWebrequest?
编辑2:
我不想上传到WebDAV文件夹或类似的东西。我想模拟一个浏览器,就像你上传你的头像到一个论坛或通过一个web应用程序中的表单上传一个文件。上传到一个使用multipart/form-data的表单。
编辑:
WebClient不覆盖我的需求,所以我正在寻找一个解决方案与HTTPWebrequest。
当前回答
我的ASP。NET上传常见问题解答中有一篇关于这方面的文章,有示例代码:使用HttpWebRequest/WebClient的RFC 1867 POST请求上传文件。此代码不将文件加载到内存中(与上面的代码相反),支持多个文件,并支持表单值、设置凭据和cookie等。
编辑:看起来好像是Axosoft把这个页面删除了。谢谢你的家伙。
它仍然可以通过archive.org访问。
其他回答
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
我永远不能让例子正常工作,我总是收到一个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);
}
}
}
我想在VB中做文件上传和添加一些参数到multipart/form-data请求。NET而不是通过正规的表单发布。 感谢@JoshCodes的回答,我找到了我一直在寻找的方向。 我发布我的解决方案是为了帮助其他人找到一种方法来使用文件和参数来执行帖子 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>
Due to the fact that I have to provide the apiKey and the signature (which is a calculated checksum of the request parameters and api key concatenated string), I needed to do it server side. The other reason I needed to do it server side is the fact that the post of the file can be performed at any time by pointing to a file already on the server (providing the path), so there would be no manually selected file during form post thus form data file would not contain the file stream.Otherwise I could have calculated the checksum via an ajax callback and submitted the file through the html post using JQuery. I am using .net version 4.0 and cannot upgrade to 4.5 in the actual solution. So I had to install the Microsoft.Net.Http using nuget cmd
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
这里有另一个我的评论的工作示例:
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是可继承的这一事实,并从那里改变底层的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