Столкнулся с проблемой прикрутил libcurl к своему проекту в Builder'е, но при попытке получить изображение выдает какую -то фигню, по гуглил так и вразумительный ответ не нашел. Вот кусок кода Code: TStringList* temp = new TStringList; CURL *curl; curl = curl_easy_init(); String data; curl_easy_setopt(curl,CURLOPT_URL,"http://www.ya.ru/logo.png"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,Writer); curl_easy_setopt(curl, CURLOPT_WRITEDATA,&data); curl_easy_setopt(curl, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows; U; Windows NT 5.1;en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1"); curl_easy_setopt(curl,CURLOPT_HEADER,1); curl_easy_perform(curl); temp->Add(data); temp->SaveToFile("image.png");
ну вообщето изображения это не текст. а тут ты работаешь как с текстовой строкой. хотя может и прокатит. но вообщето выложи калбек функцию которая пишет в буфер
here we go... Code: static size_t Writer(char *data, size_t size,size_t nmemb, AnsiString *buffer) { size_t result = 0; if(buffer != NULL) { buffer->Insert(data,buffer->Length()+1); result = size * nmemb; } return result; }
Файл: PHP: //--------------------------------------------------------------------------- struct CaptchaFile { const char *filename; FILE *stream; }; //--------------------------------------------------------------------------- static size_t CaptchaWrite(void *buffer, size_t size, size_t nmemb, void *stream) { struct CaptchaFile *out=(struct CaptchaFile *)stream; if(out && !out->stream) { out->stream=fopen(out->filename, "wb"); if(!out->stream) return -1; } return fwrite(buffer, size, nmemb, out->stream); } //--------------------------------------------------------------------------- Память: PHP: //--------------------------------------------------------------------------- static void *cap_realloc(void *ptr, size_t size) { return ptr ? realloc(ptr, size) : malloc(size); } //--------------------------------------------------------------------------- struct CaptchaBuffer { char* memory; size_t size; }; //--------------------------------------------------------------------------- static size_t CaptchaWrite(void *data, size_t size, size_t nmemb, void *buffer) { size_t realsize = size * nmemb; struct CaptchaBuffer *mem = (struct CaptchaBuffer *)buffer; mem->memory = (char*)cap_realloc(mem->memory, mem->size + realsize + 1); if(mem->memory) { memcpy(&(mem->memory[mem->size]), data, realsize); mem->size += realsize; mem->memory[mem->size] = 0; } return realsize; } //---------------------------------------------------------------------------
Мало того, что картинку в TStringList запихал, так еще и вместе с заголовком ответа... Как причем? Ты же сам спросил про либкурл.
тут тема не в этом, курл вообще не получает картинки, а то что я пихаю в тексовый файл то что должно быть бинарным, я могу так же использовать TFileStream, для этого не обязательно делать структуру. Вообщем проблема открыта. Тут дело не в том что я пишу куда-то не правильно а именно в том что курл не получает картинку.
Ты свою калбек функцию посмотри и подумай, как у тебя картинка будет скачиваться? Я тебе 2 функции привел - одна для сохранения картинки в файл, вторая для сохранения в память. Что еще нужно? Полностью код получения картинки написать?
окей, щас надо уходить приду посмотрю, но в инете смотрел там именно тема в том что сам курл не принимает имаги (имею ввиду что-то-там.ru/имаг.jpg).
2M_script Все и вправду робает, но если с записью в файл я разобрался, то с записью в память не в курил, так же не знаю можно ли приводить CaptchaBuffer->memory к строковму типу или это не получится (не стоит). Вот вообщем код на котором запоролся. Code: CURL *curl; curl = curl_easy_init(); String data,cockie; CaptchaBuffer* data1 = new CaptchaBuffer; curl_easy_setopt(curl,CURLOPT_URL,"http://www.ya.ru/logo.png"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,CaptchaWrite); curl_easy_setopt(curl, CURLOPT_WRITEDATA,data1); curl_easy_setopt(curl, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows; U; Windows NT 5.1;en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1"); curl_easy_perform(curl); Form3->Memo1->Text=String(data1->memory); FILE* stream; stream = fopen("captcha.png","wb"); fwrite(data1->memory,sizeof(data1->memory),data1->size,stream); } Проблема щас в том что в файл данные не пишутся и я вообще не уверен что они находятся в data1->memory.
Вот именно по этому лучше всего создать отдельную калбек функцию для записи в файл. Наилучшая структура тогда будет такая: 1) открываешь файл 2) хендл файла ставишь как CURLOPT_WRITEDATA 3) выполняешь curl_easy_perform 4) закрывашеь хендл файла В калбек функции просто берешь этот хендл из последнего параметра и пишешь в файл сразу. В итоге нет никаких заморочек с хранением данных и выделением памяти. потому как всё сразу пишется в файл.
2slesh Полностью с тобой согласен, но на данный момент проблема в том что я не получаю вообще данных и хотелось бы узнать почему, в случае с колбек функцией для файлов которую выложил M_Script все понятно(за что кстати говря ему спасибо), а вот с записью в память у меня проблемы уже несколько часов мучаюсь, просматриваю отладчиком он мне пишет парень в переменной нихрена нет =)))
это я просто решил сделать вроде как тестовый пример, проблема даже не в том что мне нужно в файл записать (хотя если в друг мне понадобится записать в файл я бы не хотел писать несколько колбек ф-ций) проблема в том что в своей переменной data1 нет данных вообще, а когда я проходился отладчиком по колбек функции так в блок if вообще не заходит.
Небольшие отрывки кода для примера file.h PHP: //--------------------------------------------------------------------------- typedef enum { HTTP = 0, SOCKS4 = 4, SOCKS5 = 5 } proxytype; typedef CURL* (__stdcall* c_easy_init)(); typedef CURLcode (__stdcall* c_easy_setopt)(CURL* curl, CURLoption option, ...); typedef CURLcode (__stdcall* c_easy_perform)(CURL* curl); typedef CURLFORMcode (__stdcall* c_formadd)(struct curl_httppost ** firstitem, struct curl_httppost ** lastitem, ...); typedef void (__stdcall* c_easy_cleanup)(CURL* curl); typedef void (__stdcall* c_formfree)(struct curl_httppost * form); //--------------------------------------------------------------------------- static size_t PageWrite(char *data, size_t size, size_t nmemb, String *buffer); struct CaptchaBuffer { char* memory; size_t size; }; static void *cap_realloc(void *ptr, size_t size); static size_t CaptchaWrite(void *data, size_t size, size_t nmemb, void *buffer); //--------------------------------------------------------------------------- class VK { public: // тут что-то было private: c_easy_init init; c_easy_setopt setopt; c_easy_perform perform; c_formadd formadd; c_easy_cleanup cleanup; c_formfree formfree; // тут тоже что-то было HINSTANCE hLibcurl; CURL* curl; struct CaptchaBuffer bufCaptcha; // и тут proxytype prProxyType; }; //--------------------------------------------------------------------------- file.cpp PHP: //--------------------------------------------------------------------------- static void *cap_realloc(void *ptr, size_t size) { return ptr ? realloc(ptr, size) : malloc(size); } //--------------------------------------------------------------------------- struct CaptchaBuffer { char* memory; size_t size; } //--------------------------------------------------------------------------- static size_t CaptchaWrite(void *data, size_t size, size_t nmemb, void *buffer) { size_t realsize = size * nmemb; struct CaptchaBuffer *mem = (struct CaptchaBuffer *)buffer; mem->memory = (char*)cap_realloc(mem->memory, mem->size + realsize + 1); if(mem->memory) { memcpy(&(mem->memory[mem->size]), data, realsize); mem->size += realsize; mem->memory[mem->size] = 0; } return realsize; } //--------------------------------------------------------------------------- VK::VK() : prProxyType(HTTP) { hLibcurl = LoadLibrary( "libcurl.dll" ); init = (c_easy_init)GetProcAddress(hLibcurl, "curl_easy_init"); setopt = (c_easy_setopt)GetProcAddress(hLibcurl, "curl_easy_setopt"); perform = (c_easy_perform)GetProcAddress(hLibcurl, "curl_easy_perform"); formadd = (c_formadd)GetProcAddress(hLibcurl, "curl_formadd"); cleanup = (c_easy_cleanup)GetProcAddress(hLibcurl, "curl_easy_cleanup"); formfree = (c_formfree)GetProcAddress(hLibcurl, "curl_formfree"); } //--------------------------------------------------------------------------- bool VK::Initialize() { if(!hLibcurl) return false; curl = init(); if(!curl) { FreeLibrary(hLibcurl); return false; } return true; } //--------------------------------------------------------------------------- Получение капчи ВК: PHP: //--------------------------------------------------------------------------- bool VK::GetCaptcha(void) { setopt(curl, CURLOPT_POST, 0); setopt(curl, CURLOPT_HEADER , 0); setopt(curl, CURLOPT_WRITEFUNCTION, CaptchaWrite); setopt(curl, CURLOPT_WRITEDATA, (void*)&bufCaptcha); sUrl = "http://vkontakte.ru/captcha.php?sid=" + sCaptchaSid; bufCaptcha.size = 0; setopt(curl, CURLOPT_URL, sUrl.c_str()); perform(curl); return true; } //--------------------------------------------------------------------------- Распознавание капчи: PHP: //--------------------------------------------------------------------------- String VK::AntigateCheckCaptcha() { setopt(curl, CURLOPT_HEADER , 0); setopt(curl, CURLOPT_PROXY , ""); setopt(curl, CURLOPT_PROXYTYPE , HTTP); struct curl_httppost *post = NULL; struct curl_httppost *last = NULL; formadd(&post, &last, CURLFORM_COPYNAME, "method", CURLFORM_COPYCONTENTS, "post", CURLFORM_END); formadd(&post, &last, CURLFORM_COPYNAME, "soft_id", CURLFORM_COPYCONTENTS, "5", CURLFORM_END); formadd(&post, &last, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, sAntigateKey, CURLFORM_END); formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_BUFFER, "captcha.jpg", CURLFORM_BUFFERPTR, bufCaptcha.memory, CURLFORM_BUFFERLENGTH, bufCaptcha.size, CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END); String sId = ""; sUrl = "http://antigate.com/in.php"; sPage = ""; setopt(curl, CURLOPT_URL, sUrl.c_str()); setopt(curl, CURLOPT_HTTPPOST, post); perform(curl); setopt(curl, CURLOPT_POST, 0); formfree(post); if(sPage.Pos("\r")) sPage.SetLength(sPage.Pos("\r") - 1); if(sPage.IsEmpty()) return "ERROR_REPLY_IN"; else if(sPage.Pos("ERROR_")) return sPage; else if(sPage.Pos("OK")) sId = sPage.SubString(sPage.Pos("|") + 1, sPage.Length() - sPage.Pos("|")); if(sId.IsEmpty()) return "ERROR_BAD_CAPTCHA_ID"; for(int i = 0; i < 12; ++i) { Sleep(5000); sUrl = "http://antigate.com/res.php?key=" + sAntigateKey + "&action=get&id=" + sId; sPage = ""; setopt(curl, CURLOPT_URL, sUrl.c_str()); perform(curl); if(sPage.Pos("\r")) sPage.SetLength(sPage.Pos("\r") - 1); if(sPage.IsEmpty()) return "ERROR_REPLY_GET"; else if(sPage.Pos("ERROR_")) return sPage; else if(sPage.Pos("OK")) { sPage.Delete(1, sPage.Pos("|")); return sPage; } } return "ERROR_TIMEOUT"; } //--------------------------------------------------------------------------- Сохранение в файл: PHP: TMemoryStream *ms = new TMemoryStream; ms->Write(bufCaptcha.memory, bufCaptcha.size); ms->SaveToFile("captcha.jpg"); PHP: typedef CURL* (__stdcall* c_easy_init)(); typedef CURLcode (__stdcall* c_easy_setopt)(CURL* curl, CURLoption option, ...); typedef CURLcode (__stdcall* c_easy_perform)(CURL* curl); typedef CURLFORMcode (__stdcall* c_formadd)(struct curl_httppost ** firstitem, struct curl_httppost ** lastitem, ...); typedef void (__stdcall* c_easy_cleanup)(CURL* curl); typedef void (__stdcall* c_formfree)(struct curl_httppost * form); struct CaptchaBuffer bufCaptcha; //--------------------------------------------------------------------------- static void *cap_realloc(void *ptr, size_t size) { return ptr ? realloc(ptr, size) : malloc(size); } //--------------------------------------------------------------------------- struct CaptchaBuffer { char* memory; size_t size; } //--------------------------------------------------------------------------- static size_t CaptchaWrite(void *data, size_t size, size_t nmemb, void *buffer) { size_t realsize = size * nmemb; struct CaptchaBuffer *mem = (struct CaptchaBuffer *)buffer; mem->memory = (char*)cap_realloc(mem->memory, mem->size + realsize + 1); if(mem->memory) { memcpy(&(mem->memory[mem->size]), data, realsize); mem->size += realsize; mem->memory[mem->size] = 0; } return realsize; } //--------------------------------------------------------------------------- VK::VK() : prProxyType(HTTP) { hLibcurl = LoadLibrary( "libcurl.dll" ); init = (c_easy_init)GetProcAddress(hLibcurl, "curl_easy_init"); setopt = (c_easy_setopt)GetProcAddress(hLibcurl, "curl_easy_setopt"); perform = (c_easy_perform)GetProcAddress(hLibcurl, "curl_easy_perform"); formadd = (c_formadd)GetProcAddress(hLibcurl, "curl_formadd"); cleanup = (c_easy_cleanup)GetProcAddress(hLibcurl, "curl_easy_cleanup"); formfree = (c_formfree)GetProcAddress(hLibcurl, "curl_formfree"); } //--------------------------------------------------------------------------- bool VK::Initialize() { if(!hLibcurl) return false; curl = init(); if(!curl) { FreeLibrary(hLibcurl); return false; } return true; } //--------------------------------------------------------------------------- Получение капчи ВК: PHP: //--------------------------------------------------------------------------- bool VK::GetCaptcha(void) { setopt(curl, CURLOPT_POST, 0); setopt(curl, CURLOPT_HEADER , 0); setopt(curl, CURLOPT_WRITEFUNCTION, CaptchaWrite); setopt(curl, CURLOPT_WRITEDATA, (void*)&bufCaptcha); sUrl = "http://vkontakte.ru/captcha.php?sid=" + sCaptchaSid; bufCaptcha.size = 0; setopt(curl, CURLOPT_URL, sUrl.c_str()); perform(curl); return true; } //--------------------------------------------------------------------------- Распознавание капчи: PHP: //--------------------------------------------------------------------------- String VK::AntigateCheckCaptcha() { setopt(curl, CURLOPT_HEADER , 0); setopt(curl, CURLOPT_PROXY , ""); setopt(curl, CURLOPT_PROXYTYPE , HTTP); struct curl_httppost *post = NULL; struct curl_httppost *last = NULL; formadd(&post, &last, CURLFORM_COPYNAME, "method", CURLFORM_COPYCONTENTS, "post", CURLFORM_END); formadd(&post, &last, CURLFORM_COPYNAME, "soft_id", CURLFORM_COPYCONTENTS, "5", CURLFORM_END); formadd(&post, &last, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, sAntigateKey, CURLFORM_END); formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_BUFFER, "captcha.jpg", CURLFORM_BUFFERPTR, bufCaptcha.memory, CURLFORM_BUFFERLENGTH, bufCaptcha.size, CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END); String sId = ""; sUrl = "http://antigate.com/in.php"; sPage = ""; setopt(curl, CURLOPT_URL, sUrl.c_str()); setopt(curl, CURLOPT_HTTPPOST, post); perform(curl); setopt(curl, CURLOPT_POST, 0); formfree(post); if(sPage.Pos("\r")) sPage.SetLength(sPage.Pos("\r") - 1); if(sPage.IsEmpty()) return "ERROR_REPLY_IN"; else if(sPage.Pos("ERROR_")) return sPage; else if(sPage.Pos("OK")) sId = sPage.SubString(sPage.Pos("|") + 1, sPage.Length() - sPage.Pos("|")); if(sId.IsEmpty()) return "ERROR_BAD_CAPTCHA_ID"; for(int i = 0; i < 12; ++i) { Sleep(5000); sUrl = "http://antigate.com/res.php?key=" + sAntigateKey + "&action=get&id=" + sId; sPage = ""; setopt(curl, CURLOPT_URL, sUrl.c_str()); perform(curl); if(sPage.Pos("\r")) sPage.SetLength(sPage.Pos("\r") - 1); if(sPage.IsEmpty()) return "ERROR_REPLY_GET"; else if(sPage.Pos("ERROR_")) return sPage; else if(sPage.Pos("OK")) { sPage.Delete(1, sPage.Pos("|")); return sPage; } } return "ERROR_TIMEOUT"; } //--------------------------------------------------------------------------- Сохранение в файл: PHP: TMemoryStream *ms = new TMemoryStream; ms->Write(bufCaptcha.memory, bufCaptcha.size); ms->SaveToFile("captcha.jpg");
WoW спасибо за код =) но как говорится same shit, сделал все как у тебя, теперь ругается на cap_realloc . Сделал как у тебя структуру CaptchaBuffer не динамически а в стеке и передал курлу как (void*)&data1. Если реализую динамически до просто память не выделяется в том же cap_realloc. Вообщем мистика ЗЫ Смотрю ты импортируешь ф-ции через GetProcAdress почему для этого либ файл не использовать :? Видел что в одной теме ты написал что не возможно, хотел бы сказать что это не так нужно всего лишь пропустить dll через implib и будет оки доки =)))
У меня BDS2006, пару раз пробовал, но не получилось, то ли implib кривой, то ли руки не оттуда растут. Если есть рабочий lib, залей куда-нибудь, многим пригодится.
Да беспроблем вот линка весь курл для Builder'а а именно тут заголовочные файлы dll'ки ну и собственно lib'а которую понимает Builder http://ifolder.ru/18974637
Вопрос все таки открыт вот код какой использую. может кто не поленится откмпилит у себя и найдет злосчастную ошибку. Code: //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "thread.h" #include "form.h" #pragma package(smart_init) //--------------------------------------------------------------------------- // Important: Methods and properties of objects in VCL can only be // used in a method called using Synchronize, for example: // // Synchronize(&UpdateCaption); // // where UpdateCaption could look like: // // void __fastcall TMyThread::UpdateCaption() // { // Form1->Caption = "Updated in a thread"; // } //--------------------------------------------------------------------------- static void *cap_realloc(void *ptr, size_t size) { /*String str=""; if(ptr){ if(realloc(ptr, size)==NULL){ str="Хуюшки"; } } else{ if(malloc(size)==NULL){ str="Хуюшки"; } } return ptr; */ return ptr ? realloc(ptr, size) : malloc(size); } //--------------------------------------------------------------------------- struct CaptchaBuffer { char* memory; size_t size; }; //--------------------------------------------------------------------------- static size_t CaptchaWrite(void *data, size_t size, size_t nmemb, void *buffer) { size_t realsize = size * nmemb; struct CaptchaBuffer *mem = (struct CaptchaBuffer *)buffer; mem->memory = (char*)cap_realloc(mem->memory, mem->size + realsize + 1); if(mem->memory) { memcpy(&(mem->memory[mem->size]), data, realsize); mem->size += realsize; mem->memory[mem->size] = 0; } return realsize; } __fastcall TMyThread::TMyThread(bool CreateSuspended) : TThread(CreateSuspended) { } //--------------------------------------------------------------------------- void __fastcall TMyThread::ProgresSync(){ Form3->ProgressBar1->StepBy(1); } void __fastcall TMyThread::Execute() { Synchronize(ProgresSync); TStringList* temp = new TStringList; CURL *curl; curl = curl_easy_init(); String data,cockie; CaptchaBuffer data1; data1.size=0; curl_easy_setopt(curl,CURLOPT_URL,"http://r.re.m.yahoo.com/api/res/1.2/5KhVxpvt27sNDbQecgdXag--/Zmk9Zml0O2g9NDYwO3c9Mjg1/http://c5.ah.yahoo.com:80/img/ws_5BOy0fB0rbONtKZURouVOTlgxcr3YkPfSXCYs2UASPFT8uodLtgSE00EQwS.8hQ153RK.1RKrodjHK0nrVVx5O7S.jpg"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,CaptchaWrite); curl_easy_setopt(curl, CURLOPT_WRITEDATA,(void*)&data1); curl_easy_setopt(curl, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows; U; Windows NT 5.1;en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1"); curl_easy_perform(curl); Form3->Memo1->Text=String(data1.memory); FILE* stream; stream = fopen("captcha.png","wb"); fwrite(data1.memory,sizeof(data1.memory),data1.size,stream); }