2012-02-23 39 views
8

Tôi đang cố gắng tải xuống tệp bằng FTP và ở giữa nếu kết nối chấm dứt thì nó sẽ tiếp tục từ nơi nó dừng lại. Vấn đề của tôi là sử dụng đoạn mã sau tôi có thể tiếp tục tải xuống nếu tôi đóng kết nối và sau đó kết nối lại, nhưng nếu tôi làm như vậy tại trang web của máy chủ thì tôi không thể tiếp tục tải xuống và chương trình đi vào trạng thái infinites.Làm cách nào để tiếp tục tải xuống tệp qua FTP bằng Curl trong C?

#include <stdio.h> 

#include <curl/curl.h> 

/* 
* This is an example showing how to get a single file from an FTP server. 
* It delays the actual destination file creation until the first write 
* callback so that it won't create an empty file in case the remote file 
* doesn't exist or something else fails. 
*/ 

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); 
} 


int main(void) 
{ 
    CURL *curl; 
    CURLcode res; 
    struct FtpFile ftpfile={ 
    "dev.zip", /* name to store the file as if succesful */ 
    NULL 
    }; 

    curl_global_init(CURL_GLOBAL_DEFAULT); 

    curl = curl_easy_init(); 
    if(curl) { 
    /* 
    * You better replace the URL with one that works! 
    */ 
    curl_easy_setopt(curl, CURLOPT_URL, 
        "ftp://root:[email protected]/dev.zip"); 
    /* Define our callback to get called when there's data to be written */ 
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); 
    /* Set a pointer to our struct to pass to the callback */ 
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); 

    /* Switch on full protocol/debug output */ 
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 

    res = curl_easy_perform(curl); 

    /* always cleanup */ 
    curl_easy_cleanup(curl); 

    if(CURLE_OK != res) { 
     /* we failed */ 
     fprintf(stderr, "curl told us %d\n", res); 
    } 
    } 

    if(ftpfile.stream) 
    fclose(ftpfile.stream); /* close the local file */ 

    curl_global_cleanup(); 

    return 0; 
} 

Có thể cho tôi biết làm cách nào để tiếp tục tải xuống nếu kết nối bị đóng bởi trang web từ xa. Bất kỳ trợ giúp sẽ được đánh giá

Cảm ơn,

Yuvi

+0

Có một số thứ như 'AddRange' của http trong ftp không? –

+0

có nó là có nhưng vấn đề của tôi là tôi không thể bắt lỗi nếu kết nối được đóng lại, để biết thêm chi tiết bạn có thể kiểm tra nó ở đây http://curl.haxx.se/libcurl/c/ftpuploadresume.html – Yuvi

Trả lời

2

Thêm một varaible đến struct ftpfile để biết chức năng ghi lại sự cần thiết phải appeand và nói libcurl để tiếp tục tải về từ cuối file đích bằng cách thiết lập CURLOPT_RESUME_FROM đến số byte tải đã:

struct FtpFile 
{ 
    const char *pcInfFil; 
    FILE *pFd; 
    int iAppend; 
}; 

trong chính, nếu bạn muốn tiếp tục:

012.
curl_easy_setopt(curl, CURLOPT_RESUME_FROM , numberOfBytesToSkip); 

Nếu bạn tập tin không tồn tại, hoặc nó không phải là một tải trở lại nhưng một tải mới, hãy chắc chắn để thiết lập CURLOPT_RESUME_FROM trở về 0.

Trong my_fwrite:

out->stream=fopen(out->filename, out->iAppend ? "ab":"wb"); 

PS nếu khi bạn cần phải khôi phục lại file lớn hơn một dài (2GB), nhìn vào CURLOPT_RESUME_FROM_LARGE và CURL_OFF_T_C()

Đáp lại bình luận yêu cầu thêm thông tin về làm thế nào để biết khi nào chuyển thất bại:

Sau khi bạn gọi curl dễ dàng thực hiện cuộc gọi:

CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); 

Lấy từ bối cảnh curl:

CURLINFO_HEADER_SIZE 
CURLINFO_CONTENT_LENGTH_DOWNLOAD 

Thêm chúng lại với nhau và chắc chắn rằng họ e qual

CURLINFO_SIZE_DOWNLOAD 

Nếu không cố gắng tái tạo lại ngữ cảnh.

Và đảm bảo sử dụng phiên bản mới nhất của curl, nó sẽ hết thời gian chờ sau 60 giây không nghe từ máy chủ FTP được tải xuống từ đó.

+0

cảm ơn cho câu trả lời, nhưng làm thế nào để tôi nhận biết rằng kết nối được đóng bởi trang web từ xa, chương trình mẫu đó không đi nếu điều kiện, nó vẫn ở trạng thái vô hạn ... – Yuvi

0

Bạn có thể sử dụng tham số CURLOPT_CONNECTTIMEOUT và CURLOPT_TIMEOUT để chỉ định thời gian chờ kết nối và thời gian thực thi tối đa trên cơ sở mỗi lần xử lý.

Cách khác (chỉ hoạt động nếu bạn đang sử dụng giao diện dễ dàng, không phải là đa giao diện) là sử dụng gọi lại tùy chọn socket, mà bạn có thể đặt bằng CURLOPT_SOCKOPTFUNCTION. Trong đó, bạn phải gọi setsockopt() cho tham số SO_RCVTIMEO với khoảng thời gian tối đa mà một kết nối có thể không hoạt động trước khi nó bị ngắt. tức là nếu không có byte nào được nhận trong 5 giây cuối cùng, hãy thả kết nối.

Các vấn đề liên quan