libCurl使用WriteFile WINAPI写入数据

时间:2015-05-12 10:22:35

标签: c++ winapi curl

我使用libcurl从互联网上下载数据。如果使用FILE写下载的数据是好的。但我想预先分配数据并写出来。我正在使用

CreateFile

SetFilePointer

SetEndOfFile

预先分配带有前缀大小数据的文件。之后我使用WriteFile写下载但未成功的数据。文件已损坏或失败,无法打开或使用它。这是我的简单代码,任何人都有想法修复writeData方法。谢谢大家

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>

#include <curl\curl.h>

using namespace std;
size_t writeData(void *buffer, size_t size, size_t nmemb, HANDLE *userdata){    
    BOOL bErrorFlag = FALSE;
    bErrorFlag = WriteFile(
        userdata,           // open file handle
        buffer,      // start of data to write
        (size*nmemb),  // number of bytes to write
        0, // number of bytes that were written
        NULL);  
    return nmemb;   
}
int progressData(void *ptr, double dltotal, double dlnow, double ultotal, double ulnow){    
    cout << "DOWNLOADED: " << dlnow / 1024 << "KB  TOTAL SIZE: " << dltotal / 1024 << "KB" << endl;
    return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
    CURL *curl; 
    FILE *fp;
    CURLcode res;
    string url = "http://myserver.allmedia.com/games/NgaoKiem300115/sampleFile.zip";
    string save = "E:\\Downloads\\sampleFile.zip";          

    HANDLE file = CreateFile("E:\\Downloads\\sampleFile.zip", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (file == INVALID_HANDLE_VALUE){
        cout << "ALLOCATE FILE FAIL" << endl;       
    }

    SetFilePointer(file, 486702722, NULL, FILE_BEGIN);
    SetEndOfFile(file);
    curl = curl_easy_init();
    if (curl){

        fp = fopen(save.c_str(), "wb");
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);

        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressData);
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);      

        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);

    }       
    system("pause");
    return 0;
}

2 个答案:

答案 0 :(得分:0)

您不会执行非常多的错误检查,以便谁知道可能出现的问题?这是初学者使用Win32e时最常见的错误。始终检查错误,如文档中所述。

查看代码,在开始写入文件之前,不要将文件指针移回文件的开头。仅这意味着您的代码无法正常工作。也许还有更多的错误,但我没有深入挖掘。

您最好执行一些调试。试图通过盯着代码来解决问题并不总是成功的。执行时检查程序。学习如何调试。

答案 1 :(得分:0)

你犯了很多错误:

  1. 在预先调整文件大小之后,您没有将文件指针设置回0,因此您的写入将从文件末尾开始。

  2. 您正在通过指针将文件HANDLE传递给writeData()函数,这很好,但是在调用WriteFile()时您没有取消引用该指针,所以它会总是失败。

  3. 如果WriteFile()失败,您不会向libCurl报告错误。

  4. 您正在为同一个文件打开多个不同类型的句柄,并且在下载完成后您没有关闭它们。

  5. 您正在将string而不是char*传递给CURLOPT_URL

  6. 尝试更像这样的东西:

    #include "stdafx.h"
    #include <stdio.h>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <conio.h>
    
    #include <curl\curl.h>
    
    using namespace std;
    
    size_t writeData(void *buffer, size_t size, size_t nmemb, HANDLE *userdata)
    {    
        DWORD dwWritten;
        BOOL bResult = WriteFile(
            *userdata,          // open file handle
            buffer,      // start of data to write
            (size*nmemb),  // number of bytes to write
            &dwWritten, // number of bytes that were written
            NULL));
        if (!bResult) {
            return 0;  
        }
        return dwWritten;   
    }
    
    int progressData(void *ptr, double dltotal, double dlnow, double ultotal, double ulnow)
    {    
        cout << "DOWNLOADED: " << dlnow / 1024 << "KB  TOTAL SIZE: " << dltotal / 1024 << "KB" << endl;
        return 0;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        CURL *curl; 
        CURLcode res;
        string url = "http://myserver.allmedia.com/games/NgaoKiem300115/NgaoKiem.zip";
        string save = "E:\\Downloads\\NgaoKiem.zip";            
    
        HANDLE file = CreateFileA(save.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (file == INVALID_HANDLE_VALUE) {
            cout << "CREATE FILE FAIL, ERROR " << GetLastError() << endl;       
            goto done;
        }
    
        if (SetFilePointer(file, 486702722, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
            cout << "ALLOCATE FILE FAIL, ERROR " << GetLastError() << endl;
            goto cleanup;
        }
    
        if (!SetEndOfFile(file)) {
            cout << "ALLOCATE FILE FAIL, ERROR " << GetLastError() << endl;
            goto cleanup;
        }
    
        if (SetFilePointer(file, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
            cout << "PREPARE FILE FAIL, ERROR " << GetLastError() << endl;
            goto cleanup;
        }
    
        curl = curl_easy_init();
        if (!curl) {
            cout << "CURL INIT FAIL" << endl;
            goto cleanup;
        }
    
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
    
        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressData);
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);      
    
        res = curl_easy_perform(curl);    
        if (res != CURLE_OK) {
            cout << "CURL DOWNLOAD FAIL, ERROR " << res << endl;
        }
        curl_easy_cleanup(curl);
    
    cleanup:
        CloseHandle(file);
    
    done:
        system("pause");
        return 0;
    }