cURL / Mailing Lists / curl-users / Single Mail

curl-users

Re: curl-users Digest, Vol 78, Issue 17

From: Yuvi yuvi <testandroidos51_at_gmail.com>
Date: Sat, 25 Feb 2012 14:07:06 +0530

I have done lots of mistakes, as that was my very first curl program.... :)

Now I am able to resume download where it was stopped earlier.
But my problem is that how do I get to know that connection is closed by
remote site.
For time being I am using TIME OUT otherwise program goes into the infinite
state.

On Fri, Feb 24, 2012 at 4:30 PM, <curl-users-request_at_cool.haxx.se> wrote:

> Send curl-users mailing list submissions to
> curl-users_at_cool.haxx.se
>
> To subscribe or unsubscribe via the World Wide Web, visit
> http://cool.haxx.se/cgi-bin/mailman/listinfo/curl-users
> or, via email, send a message with subject or body 'help' to
> curl-users-requemyst_at_cool.haxx.se <curl-users-request_at_cool.haxx.se>
>
> You can reach the person managing the list at
> curl-users-owner_at_cool.haxx.se
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of curl-users digest..."
>
>
> Today's Topics:
>
> 1. Re: How to resume file download through FTP ? (Dan Fandrich)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Thu, 23 Feb 2012 14:41:15 +0100
> From: Dan Fandrich <dan_at_coneharvesters.com>
> To: curl-users_at_cool.haxx.se
> Subject: Re: How to resume file download through FTP ?
> Message-ID: <20120223134114.GC4803_at_coneharvesters.com>
> Content-Type: text/plain; charset=iso-8859-1
>
> On Thu, Feb 23, 2012 at 03:12:40PM +0530, Yuvi yuvi wrote:
> > I have searched a lot but don't find any sample code for resume download
> > through File Transfer Code. I know that curl support this feature and I
> can
> > able to do this using command prompt. But how to do it programmatically.
> Even I
> > tired to write one but no luck, this code working when connection is
> closed at
> > my lapi but if connection is closed by remote site it is not working :
>
> You can use the --libcurl option in the command-line tool to see what
> options it sets. Resuming also requires seek logic in the client,
> though, which --libcurl won't give you.
>
> > #include <stdlib.h>
> > #include <stdio.h>
> >
> > #include <curl/curl.h>
> >
> >
> > struct FtpFile {
> >
> > ? const char *filename;
> >
> > ? FILE *stream;
> > };
> >
> > static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void
> *stream)
> >
> > {
> > ? struct FtpFile *out=(struct FtpFile *)stream;
> >
> > ? if(out && !out->stream) {
> >
> > ? ? /* open file for writing */
> > ? ? out->stream=fopen(out->filename, "wb");
> >
> > ? ? if(!out->stream)
> > ? ? ? return -1; /* failure, can't open file to write */
> >
> > ? }
> > ? return fwrite(buffer, size, nmemb, out->stream);
> >
> > }
> >
> >
> >
> > static size_t append_fwrite(void *buffer, size_t size, size_t nmemb,
> void *stream)
> >
> > {
> > ? struct FtpFile *out=(struct FtpFile *)stream;
> >
> > ? if(out && !out->stream) {
> >
> > ? ?// ?open file for writing
> > ? ? out->stream=fopen(out->filename, "a+");
>
> The other fopen uses the 'b' modifier, so this ought to as well.
>
> > ? ? if(!out->stream)
> > ? ? ? return -1; ?//failure, can't open file to write
> >
> > ? }
> > ? return fwrite(buffer, size, nmemb, out->stream);
> >
> > }
> >
> >
> >
> > /* parse headers for Content-Length */
> > size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void
> *stream)
> >
> > {
> > ? int r;
> > ? long len = 0;
> >
> >
> > ? /* _snscanf() is Win32 specific */
> > ? r = sscanf(ptr, ?"Content-Length: %ld\n", &len);
>
> This will fail if the server sends this line with different case. I
> believe recent versions of libcurl guarantee that curl_easy_getinfo with
> CURLINFO_CONTENT_LENGTH_DOWNLOAD will return that value (when available
> at all) by the time the first write callback is called. That would be a
> more reliable way of determining the length.
>
> >
> > ? if (r) /* Microsoft: we don't read the specs */
> >
> > ? ? *((long *) stream) = len;
> >
> > ? return size * nmemb;
> > }
> >
> >
> > /* discard downloaded data */
> > size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream)
>
> This isn't referenced anywhere. And throwing out all downloaded data is
> usually pretty wasteful. Using NOBODY as you've done is much better.
>
> > {
> > ? return size * nmemb;
> >
> > }
> >
> >
> >
> >
> > int download(CURL *curlhandle, const char * remotepath,long timeout,
> long tries)
> >
> > {
> >
> > ? long uploaded_len = 0;
> >
> > ? CURLcode r = CURLE_GOT_NOTHING;
> > ? int c;
> >
> > ? struct FtpFile ftpfile={
> > ? ? "dev.zip", ?//name to store the file as if succesful
> >
> > ? ? NULL
> > ? };
> >
> >
> >
> >
> > ? curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath);
> >
> >
> > ? if (timeout)
> > ? ? curl_easy_setopt(curlhandle, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
> >
> >
> > ? curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION,
> getcontentlengthfunc);
> >
> > ? curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len);
>
> I don't see where this value is used.
>
> >
> > ? curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, my_fwrite);
> >
> > ? curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, &ftpfile);
> >
> > ? curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-"); /* disable passive
> mode */
> >
> > ? curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);
> >
> >
> > ? curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
> >
> >
> > ? for (c = 0; (r != CURLE_OK) && (c < tries); c++) {
> >
> > ? ? /* are we resuming? */
> > ? ? if (c) { /* yes */
>
> This logic is too simplistic. The first attempt may have failed well
> before the connection to the server was even established.
>
> > ? ? ? /* determine the length of the file already written */
> > ? ? ? ? fputs("retrying.............",stderr);
> >
> > ? ? ? curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 1L);
> >
> > ? ? ? curl_easy_setopt(curlhandle, CURLOPT_HEADER, 1L);
> >
> >
> > ? ? ? r = curl_easy_perform(curlhandle);
>
> Using curl_easy_getinfo eliminates the need for this separate transfer.
>
> > ? ? ? if (r != CURLE_OK)
> >
> > ? ? ? ? continue;
> >
> > ? ? ? curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 0L);
> >
> > ? ? ? curl_easy_setopt(curlhandle, CURLOPT_HEADER, 0L);
> >
> >
> >
> >
> > ? ? ? curl_easy_setopt(curlhandle, CURLOPT_APPEND, append_fwrite);
>
> CURLOPT_APPEND takes a long, not a function pointer. I think you want
> CURLOPT_WRITEFUNCTION here.
>
> What you're missing is an ftell or fstat call and the CURLOPT_RANGE or
> CURLOPT_RESUME_FROM option to have the server start sending data from
> the last location downloaded.
>
> >
> > ? ? ? curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
> >
> > ? ? }
> > ? ? else { /* no */
> >
> > ? ? ? curl_easy_setopt(curlhandle, CURLOPT_APPEND, 0L);
> >
> > ? ? ? curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
> >
> > ? ? }
> >
> > ? ? r = curl_easy_perform(curlhandle);
> >
> > ? }
> >
> >
> >
> > ? if (r == CURLE_OK)
> >
> > ? ? return 1;
> > ? else {
> >
> > ? ? fprintf(stderr, "%s\n", curl_easy_strerror(r));
> >
> > ? ? return 0;
> > ? }
> > }
> >
> >
> > int main(int c, char **argv)
> >
> > {
> > ? CURL *curlhandle = NULL;
> >
> >
> > ? curl_global_init(CURL_GLOBAL_ALL);
> > ? curlhandle = curl_easy_init();
> >
> >
> > ? download(curlhandle, "ftp://root:password@192.168.10.1/dev.zip", ?0,
> 100);
> >
> >
> > ? curl_easy_cleanup(curlhandle);
> > ? curl_global_cleanup();
> >
> >
> > ? return 0;
> > }
>
> >>> Dan
>
>
>
> ------------------------------
>
> _______________________________________________
> curl-users mailing list
> curl-users_at_cool.haxx.se
> http://cool.haxx.se/cgi-bin/mailman/listinfo/curl-users
>
>
> End of curl-users Digest, Vol 78, Issue 17
> ******************************************
>

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-users
FAQ: http://curl.haxx.se/docs/faq.html
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2012-02-25