0

curl結果をファイルに保存するためのコールバック関数を使用しています。

size_t WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) 
{
    size_t written = fwrite(ptr, size, nmemb, stream);
    return written;
}

また、受信したファイルを数える必要がありMD5ます。しかし、ダウンロードしたファイルを再度読み込んでカウントするのは悪い考えなので、ファイルに保存するバッファを取得して、それを部分的な計算式パラメータMD5として使用したいと考えています。MD5

私が理解しているように、構造体には、ファイルに書き込まれるすべてのデータが保持される場所FILEと呼ばれるメンバーがありますが、そのサイズを知る必要があります。_baseサイズはあるべきだと思ったのでnmemb、小さなテストを行いました:

size_t WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) 
{
    size_t written = fwrite(ptr, size, nmemb, stream);
    for (int i = 0; i < nmemb; ++i)
        std::cout << stream->_base[i];
    return written;
}

この関数を追加してデータを画面に出力すると、大量のゴミが出力されることがわかりました。私の質問は、データバッファサイズを取得する方法ですか?

4

2 に答える 2

1

(注:これは、実際に尋ねられた質問ではなく、尋ねられるべきだったと思う質問への回答です。https://meta.stackexchange.com/questions/66377/what-is-the-xy-problemを参照してください)

C ライブラリの内部をいじる代わりに、独自のユーザーデータを libcurl に提供する必要があります。CURLOPT_WRITEDATA転送を初期化するときにオプションでユーザーデータを設定できます。

libcurl が単に FILE* を渡す代わりに、独自のユーザーデータを設定する可能性を提供するのは、まさにこの種のアプリケーションのためです。

大まかに言えば、コードは次のようになります。

// All error checking has been omitted; don't use this code as is.

// This is the userdata you'll be using
typedef struct FileWithMD5 {
  FILE*   file;
  MD5_CTX md5_ctx;
} FileWIthMD5;

// The transfer function we'll be using
size_t write_with_md5(char *ptr, size_t size, size_t  nmemb,
                      void *userdata);

// This function is called before the transfer is started.
// The return value needs to be passed to the finalize function.
FileWithMD5* initialize_transfer(CURL *handle, const char* filename) {
  // Allocate a userdata
  FileWithMD5* userdata = malloc(sizeof(*userdata));
  userdata->file = fopen(filename, "w");
  MD5Init(&userdata->md5_ctx);
  curl_easy_setopt(handle, CURL_WRITEDATA, userdata);
  curl_easy_setopt(handle, CURL_WRITEFUNCTION, write_with_md5);
  return userdata;
}

// This function is called after the transfer is finished.
void finalize_transfer_and_extract_md5(CURL *handle,
                                       FileWithMD5* userdata,
                                       u_int8_t md5[MD5_DIGEST_LENGTH]) {
  // Close the file, extract the MD5, and get rid of the userdata
  close(userdata->file);
  MD5Final(md5, &userdata->md5_ctx);
  free(userdata);
  curl_easy_setopt(handle, CURL_WRITEDATA, 0);
}

// Callback function
size_t write_with_md5(char *ptr, size_t size, size_t  nmemb,
                      void *vuserdata) {
  FileWithMD5* userdata = vuserdata;
  // Write the data and update the MD5
  size_t written = fwrite(ptr, size, nmemb, userdata->file);
  MD5Update(&userdata->md5_ctx, (const u_int8_t*)ptr, written);
  return written;
}
于 2013-08-19T15:24:59.120 に答える