我使用libcurl从互联网上下载数据。如果使用FILE写下载的数据是好的。但我想预先分配数据并写出来。我正在使用
预先分配带有前缀大小数据的文件。之后我使用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;
}
答案 0 :(得分:0)
您不会执行非常多的错误检查,以便谁知道可能出现的问题?这是初学者使用Win32e时最常见的错误。始终检查错误,如文档中所述。
查看代码,在开始写入文件之前,不要将文件指针移回文件的开头。仅这意味着您的代码无法正常工作。也许还有更多的错误,但我没有深入挖掘。
您最好执行一些调试。试图通过盯着代码来解决问题并不总是成功的。执行时检查程序。学习如何调试。
答案 1 :(得分:0)
你犯了很多错误:
在预先调整文件大小之后,您没有将文件指针设置回0,因此您的写入将从文件末尾开始。
您正在通过指针将文件HANDLE
传递给writeData()
函数,这很好,但是在调用WriteFile()
时您没有取消引用该指针,所以它会总是失败。
如果WriteFile()
失败,您不会向libCurl报告错误。
您正在为同一个文件打开多个不同类型的句柄,并且在下载完成后您没有关闭它们。
您正在将string
而不是char*
传递给CURLOPT_URL
。
尝试更像这样的东西:
#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;
}