Timeout problem with WC.UploadData

  • Thread starter Russell Stevens
  • Start date
R

Russell Stevens

I use a WinForm app for users to upload a file to my server. Basically one
line of code;

Response = WC.UploadData(MyUrl, "PUT", MyByteArray)

Works fine except for larger files. After about 104 seconds I get a
System.Net.WebException in System.dll. The message is "The operation has
timed out".

On my server, I have modified the machine.config file for the httpRuntime
executionTimeout and have changed it from 90 seconds to 900 seconds. Even
after rebooting the server, this has no effect.

Anyone got a clue as to what timer is causing the problem and how to fix it.
Depending on the connection speed this severly limits the size of file that
may be uploaded.

Interesting in that if you just ignore the exception, the upload sometimes
continues to completion.

Thanks
Russell Stevens
 
P

Peter Huang

Hi Russell,

I think the WebClient doesnot support the timeout properties, you may try
to use the HttpWebRequest to achieve your aim. Here goes the sample code.

I converted from C# code in the link below
http://www.netacademia.net/tudastar/default.asp?upid=554

Imports System
Imports System.IO
Imports System.Net
Imports System.Text
Namespace HttpCopy
Class App
Private args() As String
Private cred As ICredentials
Public Shared Sub Main(ByVal args() As String)
Dim app As New App
app.args = args
app.Run()
End Sub 'Main
Private Sub Run()
If args.Length < 2 Then
Usage()
Return
End If
Dim [source] As String = args(0)
Dim dest As String = args(1)
If CheckArgs() Then
cred = MakeCredentials()

If Directory.Exists([source]) Then
'Source is a folder, we have to enumerate
'all the files (not recursive)
If Not dest.EndsWith("/") Then
Console.WriteLine(("If source is a folder
destination must be" + " a folder too (/ at the end of it)."))
Return
End If

Dim file As String
For Each file In Directory.GetFiles([source])
CopyFileWithProgress(file, dest +
Path.GetFileName(file))
Next file
Else
'Only a file
If dest.EndsWith("/") Then
dest += Path.GetFileName([source])
End If
CopyFileWithProgress([source], dest)
End If
End If
End Sub 'Run

Private Sub CopyFileWithProgress(ByVal [source] As String, ByVal
dest As String)
Dim wt As TimeSpan

If CopyFile([source], dest, wt) Then
Console.WriteLine("Successfully copied in {0}.{1} sec.",
wt.Seconds, wt.Milliseconds)
End If
End Sub 'CopyFileWithProgress


Private Function CopyFile(ByVal [source] As String, ByVal dest As
String, ByRef workingTime As TimeSpan) As Boolean
Dim startTime As System.DateTime = DateTime.Now

Dim completed As Boolean = False

Dim response As String = Nothing
Try
Dim uploader As HttpWebRequest =
CType(WebRequest.Create(New Uri(dest)), HttpWebRequest)
uploader.Timeout = 60000000
uploader.Method = "PUT"
uploader.ContentLength = New FileInfo([source]).Length
uploader.Credentials = cred

Dim sourceStream As New FileStream([source], FileMode.Open,
FileAccess.Read, FileShare.ReadWrite)

Console.WriteLine("Copying {0} to {1}",
Path.GetFullPath([source]), dest)
Dim requestStream As Stream = uploader.GetRequestStream()
Dim buff(4095) As Byte

Dim pos As Integer = 0
pos = sourceStream.Read(buff, 0, buff.Length)
While pos <> 0 'ToDo: Unsupported feature: assignment
within expression.
requestStream.Write(buff, 0, pos)
pos = sourceStream.Read(buff, 0, buff.Length)
End While
Dim resp As HttpWebResponse = CType(uploader.GetResponse(),
HttpWebResponse)
Dim respReader As New StreamReader(resp.GetResponseStream())
response = respReader.ReadToEnd()
completed = True
Catch ex As Exception
Console.WriteLine("Error while uploading file {0}, a hiba
oka:" + ControlChars.Lf + " {1}", [source], ex)
Console.WriteLine(ControlChars.Lf + "Http response:" +
ControlChars.Lf + " {0}", IIf(response Is Nothing, "No Response", response))
Finally
workingTime = System.DateTime.op_Subtraction(DateTime.Now,
startTime)
End Try
Return completed
End Function 'CopyFile


Private Function MakeCredentials() As ICredentials
Dim user, pass, domain As String
user = GetSwitchValue("user")
pass = GetSwitchValue("password")
domain = GetSwitchValue("domain")
If domain Is Nothing Then
domain = ""
End If
If Not (user Is Nothing) Then
Return New NetworkCredential(user, pass, domain)
Else
Return CredentialCache.DefaultCredentials
End If
End Function 'MakeCredentials


Private Function GetSwitchValue(ByVal switchName As String) As
String
switchName = switchName.ToLower()
Dim arg As String
For Each arg In args
If arg.ToLower().StartsWith(("/" + switchName + ":")) Then
Return arg.Split(":".ToCharArray())(1).Trim()
End If
Next arg
Return Nothing
End Function 'GetSwitchValue


Private Function CheckArgs() As Boolean
'is dest a valid uri?
Try
Dim destUri As New Uri(args(1))
Return True
Catch
Console.WriteLine("Invalid destination URL: {0}", args(1))
Return False
End Try
End Function 'CheckArgs


Private Sub Usage()
Dim usage As String = "httpcopy: copies local files to http
server via HTTP PUT method." + ControlChars.Cr + ControlChars.Lf +
"Copyright (C) NetAcademia 1900-2003. No right reserved." + ControlChars.Cr
+ ControlChars.Lf + "Author: (e-mail address removed)" + ControlChars.Cr
+ ControlChars.Lf + "Usage:" + ControlChars.Cr + ControlChars.Lf +
"httpcopy sourceFile destFile" + " [/user:uname, /password:pass,
/domain:dname]" + ControlChars.Cr + ControlChars.Lf + "Examples:" +
ControlChars.Cr + ControlChars.Lf + "httpcopy a.txt
http://www.netacademia.net/xxx/b.txt" + ControlChars.Cr + ControlChars.Lf +
"httpcopy a.txt http://www.netacademia.net/xxx/" + ControlChars.Cr +
ControlChars.Lf + "httpcopy c:\temp http://www.netacademia.net/xxx/" +
ControlChars.Cr + ControlChars.Lf
Console.WriteLine(usage)
End Sub 'Usage
End Class 'App
End Namespace 'HttpCopy


If you have any concern on this issue, please post here.

Regards,
Peter Huang
Microsoft Online Partner Support
Get Secure! www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
R

Russell Stevens

Peter,

Thanks - using HttpWebRequest does get around the timeout problem with
WebClient.

MICROSOFT - both HttpWebRequest and WebClient STILL upload each byte THREE
times when you use basic authentication - ie - a 3 MB file requires you to
upload 9 MB. This was reported years ago - when is it going to be fixed?

Also, the fact that WebClient cannot be used as documented to upload a file
that takes more than 100 seconds makes is pretty useless. Figure out how
large a file can be uploaded in 100 seconds over a dialup connection. Then
since most uploads will require at least basic authentication, divide that
by three (unless you can figure out how to send your own headers which is
not documented anywhere). You are only left with the ability to upload very
small files - please fix this mess.

Thanks
Russell Stevens
 
P

Peter Huang

HI Russell,
MICROSOFT - both HttpWebRequest and WebClient STILL upload each byte THREE
times when you use basic authentication - ie - a 3 MB file requires you to
upload 9 MB. This was reported years ago - when is it going to be fixed?

I am sorry, but what do you mean both HttpWebRequest and WebClient STILL
upload each byte THREE times when you use basic authentication. Based on my
test, if I provided the username and password, the packet will be directed
accepted by the webserver. ( I trace by using NetMon)

So can you provide the steps for me to reproduce the problem.

If you have any concern on this issue, please post here.

Regards,
Peter Huang
Microsoft Online Partner Support
Get Secure! www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
R

Russell Stevens

Peter,

<<So can you provide the steps for me to reproduce the problem.>>

When using WC.UploadData with credentials for basic authentication, every
packet is sent 3 times. ie - every packet is authenticated instead of
authenticating once, and then uploading the entire file. Microsoft verified
that this is indeed a problem (SRX030305602529). The work around is to NOT
use credentials but to send the authentication information in custom
headers.

So, WC.UploadData is limited to 100 seconds (not documented and not
adjustable), and when used as documented with credentials for basic
authentication, sends every byte three times, so the maximum file that it
may upload is what you can get on a normal dialup for 33 seconds. ie - 49
Kbps for 33 seconds is 202 KBytes. In other words, it is USELESS - Microsoft
needs to fix this.

If you want to verify it all you need to do is use WC.UploadData with
credentials for basic authentication and upload to a site that requires
basic authentication and look at the bytes sent in Task Manager. Uploading a
1 MB file will result in sending 3 MB (plus change for overhead). Note that
this was NOT a problem in VB6 using XMLHTTP.

Thanks
Russ Stevens
 
P

Peter Huang

Hi Russell,

Thank you for using MSDN Newsgroup!

As for the problem that the Webclient will upload data three times to an
webserver with basic authentication, I have contacted the Case Owner of
SRX030305602529. If I get any updated information, I will update with you
as soon as possible.

If you have any concern on this issue, please post here.

Regards,
Peter Huang
Microsoft Online Partner Support
Get Secure! www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top