|
Thanks for posting this, it works great for storing cookies, just as advertised
I am having one issue, though. I have a single WebClientEx object that I share between methods, because I am using the Async methods and need to access the WebClientEx object after the operation has completed (via an event handler). Each function that initiates an action, like downloading or uploading some information, starts with:
wc = new WebClientEx();
Regardless of this, I am getting a WebException thrown that states, "The request was aborted: The request was canceled," the second time I use a function. The exception is thrown from:
protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
Oddly enough, as long as I don't use the same function twice, it does not error; for example: upload once, then download once works but upload once, then upload again fails.
I'm not sure if this is a result of your code or an error in my perception of WebClient, but if you have any suggestions, they would be much appreciated. Just to note, the problem that I am trying to solve is persisting the cookies obtained in WebClientEx between application instances, so I need to be able to access the cookie data from the Download*Completed and Upload*Completed event handlers.
Thank you.
|
|
|
|
|
Same problem here, but for me evertytime, when I want to use function after I've used another one error is raised.
|
|
|
|
|
I don't think so it could be possible, because
e.g.
i am trying to login on remote server through web client, in that case i have to maintain cookies in my cookie container, but still it couldn't possible using web client control to maintain cookie till logged in.
If anyone have solution for that problem so please help me.
Regards
Absolute Solution
sourabhsgandhi@gmail.com
|
|
|
|
|
Nice article- thanks!
This function only works with the GET method curently- here is a quick tip to add POST functionality to this guy:
<br />
public static string UploadFile(..., string method)
{<br />
...<br />
<br />
Uri uri = null;<br />
if(method == "GET")<br />
{<br />
string postdata = "?";<br />
if(querystring != null)<br />
{<br />
foreach(string key in querystring.Keys)<br />
{<br />
postdata += key +"=" + querystring.Get(key)+"&";<br />
}<br />
}<br />
uri = new Uri(url + postdata);<br />
}<br />
else<br />
uri = new Uri(url);<br />
<br />
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");<br />
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(uri);<br />
webrequest.CookieContainer = cookies;<br />
webrequest.ContentType = "multipart/form-data; boundary=" + boundary;<br />
webrequest.Method = method;<br />
<br />
StringBuilder sb = new StringBuilder();<br />
<br />
if(method == "POST")<br />
{<br />
if(querystring != null)<br />
{<br />
foreach(string key in querystring.Keys)<br />
{<br />
sb.Append("--" + boundary + "\r\n" + <br />
"Content-Disposition: form-data; name=\"" + key + "\"\r\n\r\n" +<br />
querystring.Get(key) + "\r\n");<br />
}<br />
} <br />
} <br />
<br />
sb.Append("--");<br />
sb.Append(boundary);<br />
...<br />
Hope this helps someone trying to POST files and other data.
|
|
|
|
|
I managed to get it working for post forms.. modified code below..may be of use to others.
Public Function UploadFileEx2(ByVal theReferer As String, ByVal postMethod As String, ByVal uploadfilename As String, ByVal url As String, ByVal fileFormName As String, ByVal contenttype As String, ByVal querystring As System.Collections.Specialized.NameValueCollection, ByVal cookies As CookieContainer) As String<br />
Try<br />
Dim uri As Uri<br />
<br />
If (fileFormName Is Nothing) OrElse (fileFormName.Length = 0) Then<br />
fileFormName = "file"<br />
End If<br />
If (contenttype Is Nothing) OrElse (contenttype.Length = 0) Then<br />
contenttype = "application/octet-stream"<br />
End If<br />
Dim postdata As String<br />
<br />
<br />
postdata = "?"<br />
If Not (querystring Is Nothing) Then<br />
For Each key As String In querystring.Keys<br />
postdata += key + "=" + querystring.Get(key) + "&"<br />
Next<br />
End If<br />
<br />
<br />
If postMethod = "POST" Then<br />
uri = New Uri(url)<br />
Else<br />
uri = New Uri(url + postdata)<br />
End If<br />
<br />
<br />
<br />
Dim boundary As String = "----------" + DateTime.Now.Ticks.ToString("x")<br />
Dim webrequest As HttpWebRequest<br />
webrequest = HttpWebRequest.Create(uri)<br />
webrequest.CookieContainer = cookies<br />
webrequest.ContentType = "multipart/form-data; boundary=" + boundary<br />
<br />
webrequest.Method = postMethod<br />
<br />
Dim sb As StringBuilder = New StringBuilder<br />
<br />
<br />
If postMethod = "POST" Then<br />
<br />
For Each key As String In querystring.Keys<br />
sb.Append("--")<br />
sb.Append(boundary)<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append("Content-Disposition: form-data; name=""")<br />
sb.Append(key)<br />
sb.Append("""" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append(querystring.Get(key))<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
Next<br />
<br />
End If<br />
<br />
<br />
<br />
sb.Append("--")<br />
sb.Append(boundary)<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append("Content-Disposition: form-data; name=""")<br />
sb.Append(fileFormName)<br />
sb.Append("""; filename=""")<br />
sb.Append(Path.GetFileName(uploadfilename))<br />
sb.Append("""")<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append("Content-Type: ")<br />
sb.Append(contenttype)<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
Dim postHeader As String = sb.ToString<br />
Dim postHeaderBytes As Byte() = Encoding.UTF8.GetBytes(postHeader)<br />
Dim boundaryBytes As Byte() = Encoding.ASCII.GetBytes("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "--" + boundary + "" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
Dim fileStream As FileStream = New FileStream(uploadfilename, FileMode.Open, FileAccess.Read)<br />
Dim length As Long = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length<br />
webrequest.ContentLength = length<br />
webrequest.Referer = theReferer<br />
Dim requestStream As Stream = webrequest.GetRequestStream<br />
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length)<br />
Dim sendBuffer(Math.Min(4096, fileStream.Length)) As Byte<br />
Dim bytesRead As Integer = 0<br />
'Dim r As New BinaryReader(fileStream)<br />
<br />
Do<br />
bytesRead = fileStream.Read(sendBuffer, 0, sendBuffer.Length)<br />
If bytesRead = 0 Then Exit Do<br />
requestStream.Write(sendBuffer, 0, bytesRead)<br />
Loop<br />
<br />
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)<br />
requestStream.Flush()<br />
requestStream.Close()<br />
<br />
Dim responce As WebResponse = webrequest.GetResponse<br />
Dim s As Stream = responce.GetResponseStream<br />
Dim sr As StreamReader = New StreamReader(s)<br />
Dim buf As String = sr.ReadToEnd<br />
Return sr.ReadToEnd<br />
Catch ex As Exception<br />
MsgBox("Error in uploadfileEx:" & ex.ToString)<br />
Return ""<br />
End Try
|
|
|
|
|
The line:
byte[] boundaryBytes =
Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
Should be:
byte[] boundaryBytes =
Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n")
It needs the two extra hyphens at the end otherwise you'll get an error 400 returned from the server.
I hope this helps someone as it nearly drove me insane !
|
|
|
|
|
|
I get time-out exception when I try to upload file throught proxy
I've added webrequest.Proxy = new WebProxy(ProxyHost, ProxyPort) but it doesn't help
|
|
|
|
|
when i try this code i have an error withs files greater than 7 MB...
here is this error:
(traduction frome french please forgive my bad english)
System.IO.IOException: unable to write data to the transport connection: and blocking operation had been interrupted by a call of WSACancellBlockingCall
doeas anybody having a clue on how resolving it?
thx
warenbe
|
|
|
|
|
Not sure if you are still looking for this, but we had what I think is your error, the HttpWebRequest has a Timeout property, which defaults to 100000 ms, we upped that and it now seems to be working for larger files.
If anyone else is getting the error: IO.Exception, Cannot close stream until all bytes are written, this is another way this expresses itself.
|
|
|
|
|
Well my error diseapeared and now i'm able to send a file greater than 100MB
but i'm not using your function: i'm using WebClient.UploadFileAsync from the .net framework 2.0
it work fine and do the same thing as yuor function but we don't have full control of what is sent... sorry for my bad english
|
|
|
|
|
Can you post your whole function code how you r able to send 100 mb file.
|
|
|
|
|
|
how can asp file recieve my request
sdfsdfsdf
|
|
|
|
|
Is there a way to receive some type of response from the server to see if it was successful or not?
|
|
|
|
|
Is there any way of hooking a progress bar into this function to give the user some idea of how fast the data is being transferred?
|
|
|
|
|
// Write out the file contents
byte[] buffer = new Byte[4096];
int bytesRead = 0;
int totalBytes =0;
while ( (bytesRead = fileStream.Read(buffer, 0, 4096)) != 0 )
{
requestStream.Write(buffer, 0, bytesRead);
totalBytes +=bytesRead;
double percentDone = totalBytes/(double) fileStream.Length;
//update progress here
}
Note: this is not tested or compliled at all so it may crash in one way or another but I think you can get the point.
|
|
|
|
|
It doesn't work because the data appears be transfered only after requestStream.Close()
|
|
|
|
|
my understanding is that ur while condition reads the entire file into through each loop. anyways i wrote something that works for the interested.
ps. (great job on the class im using it a lot)
Stream requestStream = webrequest.GetRequestStream();
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
// Reads all bytes and places it in byte array
byte[] buffer = File.ReadAllBytes(uploadfile);
int bytesRead = 0;
int i = 0; // used to keep track of bytesRead length in buffer
while ((bytesRead = fileStream.ReadByte()) != -1) {
requestStream.WriteByte(buffer[i]);
int percent = Convert.ToInt32((i / (double)fileStream.Length) * 100);
Debug.write("%" + percent.ToString()); // my debug
i++;
}
enjoy!
|
|
|
|
|
Hi,
Ive tryed your code to upload a file but I got the 401.1 error. This error means that I dont have the required credentials, this is strange because I'm working with localhost. I've tryed to upload the file using the browser and it works fine, but from my application I got this error.
Id like to have some help on this, thanks.
please use Antonio.mm.neves@gmail.com
|
|
|
|
|
Thanks for the vb.net version. It was just what i was looking for. I had to make a small change to the code to make it work. I just had to swap 2 lines around while creating the post string. Here's the updated version
------------------------------------------------------------------------
Public Shared Function UploadFile(ByVal uploadfilename As String, ByVal url As String, ByVal fileFormName As String, ByVal contenttype As String, ByVal querystring As System.Collections.Specialized.NameValueCollection, ByVal cookies As CookieContainer) As String
If (fileFormName Is Nothing) OrElse (fileFormName.Length = 0) Then
fileFormName = "file"
End If
If (contenttype Is Nothing) OrElse (contenttype.Length = 0) Then
contenttype = "application/octet-stream"
End If
Dim postdata As String
postdata = "?"
If Not (querystring Is Nothing) Then
For Each key As String In querystring.Keys
postdata += key + "=" + querystring.Get(key) + "&"
Next
End If
Dim uri As Uri = New Uri(url + postdata)
Dim boundary As String = "----------" + DateTime.Now.Ticks.ToString("x")
Dim webrequest As HttpWebRequest = CType(webrequest.Create(uri), HttpWebRequest)
webrequest.CookieContainer = cookies
webrequest.ContentType = "multipart/form-data; boundary=" + boundary
webrequest.Method = "POST"
Dim sb As StringBuilder = New StringBuilder
sb.Append("--")
sb.Append(boundary)
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")
sb.Append("Content-Disposition: form-data; name=""")
sb.Append(fileFormName)
sb.Append("""; filename=""")
sb.Append(Path.GetFileName(uploadfilename))
sb.Append("""")
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")
sb.Append("Content-Type: ")
sb.Append(contenttype)
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")
Dim postHeader As String = sb.ToString
Dim postHeaderBytes As Byte() = Encoding.UTF8.GetBytes(postHeader)
Dim boundaryBytes As Byte() = Encoding.ASCII.GetBytes("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "--" + boundary + "" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")
Dim fileStream As FileStream = New FileStream(uploadfilename, FileMode.Open, FileAccess.Read)
Dim length As Long = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length
webrequest.ContentLength = length
Dim requestStream As Stream = webrequest.GetRequestStream
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length)
Dim sendBuffer(Math.Min(4096, fileStream.Length)) As Byte
Dim bytesRead As Integer = 0
'Dim r As New BinaryReader(fileStream)
Do
bytesRead = fileStream.Read(sendBuffer, 0, sendBuffer.Length)
If bytesRead = 0 Then Exit Do
requestStream.Write(sendBuffer, 0, bytesRead)
Loop
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)
requestStream.Flush()
requestStream.Close()
Dim responce As WebResponse = webrequest.GetResponse
Dim s As Stream = responce.GetResponseStream
Dim sr As StreamReader = New StreamReader(s)
Return sr.ReadToEnd
End Function
|
|
|
|
|
Thanks your code. It is very nice.
But, I in my php whenever use move_uploaded_file return false.
Can you upload this code in php?
|
|
|
|
|
Hi, I need to post files to a webserver from pocketpc, but teh .NET CF does not support Cookies, so I just remove references to cookies in you code. Is that correct or do I need to make more changes?
Thank you,
Sergio
|
|
|
|
|
I use the following code successfuly with easyphp 1.8, remove the cookiecontainer because .netCF does no support it. Remember to change the target host. Used the same php script as above. I uploaded 4 files, it does not hang or give any errors.
------------------------ CODE START ------------------------
public void DoTest()
{
NameValueCollection querystring = new NameValueCollection();
querystring["uname"]="uname";
querystring["passwd"]="snake3";
string uploadfile;// set to file to upload
string outdata;
uploadfile = "\\My Documents\\image.jpg";
outdata = UploadFileEx(uploadfile, "http://remotehostIP:80/test.php", "uploadfile", "image/pjpeg", querystring);
MessageBox.Show(outdata);
}
private static string UploadFileEx(string uploadfile, string url,
string fileFormName, string contenttype, NameValueCollection querystring)
{
if(fileFormName == null || fileFormName.Length == 0)
fileFormName = "file";
if(contenttype == null || contenttype.Length == 0)
contenttype = "application/octet-stream";
string postdata;
postdata = "?";
if (querystring != null)
{
foreach(string key in querystring.Keys)
postdata += key+"="+querystring.Get(key)+"&";
}
EscapedUri uri=new EscapedUri(url+postdata);
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(uri);
webrequest.ContentType = "multipart/form-data; boundary="+boundary;
webrequest.Method = "POST";
webrequest.AllowWriteStreamBuffering = false;
// Build up the post message header
StringBuilder sb=new StringBuilder();
sb.Append("--");
sb.Append(boundary);
sb.Append("\r\n");
sb.Append("Content-Disposition: form-data; name=\"");
sb.Append(fileFormName);
sb.Append("\"; filename=\"");
sb.Append(Path.GetFileName(uploadfile));
sb.Append("\"");
sb.Append("\r\n");
sb.Append("Content-Type: ");
sb.Append(contenttype);
sb.Append("\r\n");
sb.Append("\r\n");
string postHeader=sb.ToString();
byte[] postHeaderBytes=Encoding.UTF8.GetBytes(postHeader);
// Build the trailing boundary string as a byte array
// ensuring the boundary appears on a line by itself
byte[] boundaryBytes=Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
FileStream fileStream=new FileStream(uploadfile, FileMode.Open, FileAccess.Read);
long length=postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length;
webrequest.ContentLength = length;
Stream requestStream=webrequest.GetRequestStream();
// Write out our post header
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
// Write out the file contents
byte[] buffer = new Byte[checked((uint)Math.Min(4096,(int)fileStream.Length))];
int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
while (bytesRead != 0 )
{
requestStream.Write(buffer, 0, bytesRead);
bytesRead = fileStream.Read(buffer, 0, buffer.Length);
}
fileStream.Close();
// Write out the trailing boundary
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
requestStream.Flush();
requestStream.Close(); //very important
string result="";
WebResponse response=webrequest.GetResponse();
if (webrequest.HaveResponse)
{
Stream s=response.GetResponseStream();
StreamReader sr=new StreamReader(s);
result = sr.ReadToEnd();
sr.Close();
s.Close();
response.Close();
}
buffer = null;
fileStream = null;
uri = null;
return result;
}
------------------------ CODE END ------------------------
|
|
|
|
|
Thanks! A great help. I translated this to vb.net for our project. i will post it here if anyone is interested in it:
<br />
<br />
<br />
Public Shared Function UploadFile(ByVal uploadfilename As String, ByVal url As String, ByVal fileFormName As String, ByVal contenttype As String, ByVal querystring As System.Collections.Specialized.NameValueCollection, ByVal cookies As CookieContainer) As String<br />
Try<br />
If (fileFormName Is Nothing) OrElse (fileFormName.Length = 0) Then<br />
fileFormName = "file"<br />
End If<br />
If (contenttype Is Nothing) OrElse (contenttype.Length = 0) Then<br />
contenttype = "application/octet-stream"<br />
End If<br />
Dim postdata As String<br />
postdata = "?"<br />
If Not (querystring Is Nothing) Then<br />
For Each key As String In querystring.Keys<br />
postdata += key + "=" + querystring.Get(key) + "&"<br />
Next<br />
End If<br />
Dim uri As Uri = New Uri(url + postdata)<br />
<br />
<br />
Dim boundary As String = "----------" + DateTime.Now.Ticks.ToString("x")<br />
Dim webrequest As HttpWebRequest = CType(webrequest.Create(uri), HttpWebRequest)<br />
webrequest.CookieContainer = cookies<br />
webrequest.ContentType = "multipart/form-data; boundary=" + boundary<br />
webrequest.Method = "POST"<br />
<br />
<br />
<br />
Dim sb As StringBuilder = New StringBuilder<br />
sb.Append(boundary)<br />
sb.Append("--")<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append("Content-Disposition: form-data; name=""")<br />
sb.Append(fileFormName)<br />
sb.Append("""; filename=""")<br />
sb.Append(Path.GetFileName(uploadfilename))<br />
sb.Append("""")<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append("Content-Type: ")<br />
sb.Append(contenttype)<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
sb.Append("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
Dim postHeader As String = sb.ToString<br />
Dim postHeaderBytes As Byte() = Encoding.UTF8.GetBytes(postHeader)<br />
Dim boundaryBytes As Byte() = Encoding.ASCII.GetBytes("" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "--" + boundary + "" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "")<br />
Dim fileStream As FileStream = New FileStream(uploadfilename, FileMode.Open, FileAccess.Read)<br />
Dim length As Long = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length<br />
webrequest.ContentLength = length<br />
Dim requestStream As Stream = webrequest.GetRequestStream<br />
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length)<br />
Dim sendBuffer(Math.Min(4096, fileStream.Length)) As Byte<br />
Dim bytesRead As Integer = 0<br />
'Dim r As New BinaryReader(fileStream)<br />
<br />
Do<br />
bytesRead = fileStream.Read(sendBuffer, 0, sendBuffer.Length)<br />
If bytesRead = 0 Then Exit Do<br />
requestStream.Write(sendBuffer, 0, bytesRead)<br />
Loop<br />
<br />
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)<br />
requestStream.Flush()<br />
requestStream.Close()<br />
<br />
Dim responce As WebResponse = webrequest.GetResponse<br />
Dim s As Stream = responce.GetResponseStream<br />
Dim sr As StreamReader = New StreamReader(s)<br />
Return sr.ReadToEnd<br />
Catch Exc As Exception<br />
Debug.WriteLine(ControlChars.Cr + "Exception: " & Exc.Message)<br />
<br />
End Try<br />
End Function<br />
<br />
<br />
|
|
|
|
|