uploading with curl
Jonas Drewsen
jdrewsen at nospam.com
Tue Apr 17 13:03:56 PDT 2012
On Tuesday, 17 April 2012 at 07:07:06 UTC, Gleb wrote:
> Gentlemen,
>
> While working with curl library, I would like to discuss a few
> more issues I faced with, if you don't mind.
>
> Here is the code sample I use:
>
> auto f = new std.stream.BufferedFile("file.zip",
> FileMode.In);
> scope (exit) f.close();
> auto client = FTP();
> client.verbose(true);
> client.url = "ftp://192.168.110.58/file.zip";
> client.setAuthentication("user", "pass");
> client.contentLength = cast(size_t)f.size;
> client.handle.set(CurlOption.upload, 1L);
> client.onSend = (void[] data)
> {
> return f.read(cast(ubyte[])data);
> };
> client.perform();
>
> 1. TIMEOUTS
>
> The code sample will work great if file.zip is small.
> If the file is big enough, we will get the following result:
>
> * Connecting to 192.168.110.58 (192.168.110.58) port 1468
> > TYPE I
> < 200 Type set to I
> > STOR file.zip
> < 150 Opening BINARY mode data connection for file.zip
> * Operation timed out after 120105 milliseconds with
> 687751168 bytes received
> * Closing connection #0
> * Timeout was reached
> std.net.curl.CurlTimeoutException at std\net\curl.d(3348): Timeout
> was reached on handle 16BCB60
>
> So we were disconnected from server because of the timeout. To
> avoid this behavior I use the following:
>
> client.dataTimeout(dur!"weeks"(10));
>
> I'm not sure if we really need this kind of timeout so I use
> the really big value. Anyway, I believe the default value of
> 120 seconds is not enough for practical usage of file transfer
> protocol. Maybe it's suitable for HTTP only?
>
> By the way, for some reason I can't use the value more then 10
> weeks. In this case we can't even connect to server:
>
> * About to connect() to 192.168.110.58 port 21 (#0)
> * Trying 192.168.110.58...
> * connected
> * Connected to 192.168.110.58 (192.168.110.58) port 21 (#0)
> * server response timeout
> * Closing connection #0
> * Timeout was reached
> std.net.curl.CurlTimeoutException at std\net\curl.d(3348):
> Timeout was reached on handle 164CB60
>
> Of course, even bigger value is not necessary, but I'm not sure
> this behavior is correct.
This is one of the many reasons I believe we should do our own
network library. Curl only support timeouts for connecting and
for the entire transfer. What you really want is better control
with sane defaults: DNS lookup timeout, connect timeout,
read/write activity timeout and timout for the entire operation.
Default "entire operation" timeout should be infinity and the
rest just some qualified guesses.
Anyway... I think the current default timeouts are how they
should be.
Regarding the 10 week limit you're mentioning please see the docs
for the Duration type:
http://dlang.org/phobos/core_time.html#Duration
>
> 2. PROGRESSBAR
>
> I've added the following to the above example:
> client.onProgress = delegate int(size_t dlTotal, size_t
> dlNow, size_t ulTotal, size_t ulNow)
> {
> return 0;
> };
>
> When compiled and run we will see the following:
>
> > STOR file.zip
> < 150 Opening BINARY mode data connection for file.zip
> * We are completely uploaded and fine
> * Remembering we are in dir ""
> < 226 Transfer complete
> * Connection #0 to host 192.168.110.58 left intact
> > QUIT
> std.net.curl.CurlException at std\net\curl.d(3365): Progress
> callback called on cleaned up Curl instance
>
> It looks like onProgress was called when the file was uploaded
> and the data connection was closed. What am I doing wrong?
> Should I return any other value when ulNow == ulTotal? In code
> examples in the documentation onProgress does not return any
> value, but it must.
>
> Maybe it would be better to use some simple progress bar by
> default when curl.verbose was true? At least something like
> this:
>
> static const bStr = replicate("\b", 20);
> static float perc;
> client.onProgress = delegate int(size_t dlTotal, size_t
> dlNow, size_t ulTotal, size_t ulNow)
> {
> perc = ulTotal ? cast(real)ulNow/cast(real)ulTotal*100
> : 0;
> writef("%s* %.2f%c uploaded", bStr, perc, '%');
> return 0;
> };
>
>
> Thank you in advance for your opinion on this issues.
You should always return 0 if you do not want to abort the job.
What you're describing sounds like a bug and I'll have a look at
it.
I think that including the progress in the verbose mode per
default will generate too much noise.
/Jonas
More information about the Digitalmars-d
mailing list