2009-04-14 13 views
9

Estoy usando C++ sin .NET en Win32, ¿cómo puedo descargar una imagen a través de HTTP desde un sitio web sin tener que reinventar la rueda? ¿Hay una API o biblioteca que proporciona una función única para hacer esto?¿Cómo descargar una imagen de una URL a un directorio local?

http://mywebsite/file.imgext -> C: \ ruta \ a \ dir \ file.imgext

+2

Cuando la mayoría de las respuestas no n Para satisfacerte, lo más probable es que la pregunta no se haga correctamente. Verifique esto antes de preguntar: http://www.catb.org/~esr/faqs/smart-questions.html –

+1

¿Qué le hace pensar que soy grosero? Solo estoy buscando una solución que me haga reinventar la rueda. Escribir 20 líneas es reinventar la rueda, escribir 6 líneas no lo es. No tienes que defenderte ... No es mi intención ser grosera contigo. –

+0

ha comentado cualquier respuesta razonable, algunas con el argumento de que lo sabía, o lo ha intentado. Por lo tanto, la pregunta no es correcta en sí misma: toda la información que ingresa en la Q, como respuestas útiles obtendrá (revise el enlace, vale la pena leerlo). –

Respuesta

7

usted podría utilizar cURLpp

havn't I usado todavía, pero example20 parece que podría resolver tu problema.

+0

se intentó primero libcurl, lo que provocó bloqueos, desconociendo una versión de C++. Sí, tiene el mismo estilo que el primer código que teníamos, lo hacía en 6 líneas. –

+0

¿Por qué 'resultó en fallas'? Con lo comúnmente utilizada que es la biblioteca, asumiría que el error está de tu parte y no de ellos. –

+0

Si está utilizando libcurl como una DLL Win32, DEBE usar la CURLOPT_WRITEFUNCTION si establece CURLOPT_WRITEDATA, o experimentará bloqueos. ==> Me lleva de vuelta a reinventar la rueda. –

2
+0

Esto requiere que abra una conexión, que me comunique, que la descargue y la escriba en un archivo mediante una transmisión en búfer. ¿No existe una manera más fácil de hacer esto? Otros idiomas pueden hacer esto usando una sola línea. –

+0

Comportamiento grosero evoca respuestas groseras: luego use otro idioma. –

+0

Por cierto, no es una cuestión de idioma, es una biblioteca ... –

1

Si está comenzando un nuevo proceso está bien, puede echar un vistazo a WGET. (E incluso si no es así, las fuentes están disponibles, se puede mirar allí para ver cómo se ha implementado.)

+0

Bueno, es una solución rápida pero no eficiente y produce sobrecarga. –

2

Puede usar las clases WinInet o WinHTTP en C++. Estas son las API nativas de Win32, que resumen parte del trabajo de obtener y recibir archivos de Internet.

He utilizado WinInet con gran éxito para hacer exactamente lo que estás tratando de hacer.

+0

Esto requiere que abra una conexión, que me comunique, la descargue y la escriba en un archivo utilizando una transmisión en búfer. –

+0

Aquí hay un código de muestra de Microsoft sobre el uso de WinInet para una transferencia FTP: http://support.microsoft.com/kb/q238273/ – CLaRGe

+0

Lo tendré en cuenta si necesito escribir un cliente con capacidades de FTP, gracias. Aún así, esto me requeriría reinventar la descarga de un archivo a través de HTTP a mi disco duro local. –

0

Utilizando POCO para esto ahora. :-)

6

WinInet API son más fáciles de lo que piensa

Aquí es un completo programa de consola Win32. Se puede compilar con VS 2010 Express y descargar Windows SDK para obtener WinInit.


// imaged.cpp : Defines the entry point for the console application. 
// 
// Copy file from internet onto local file 
//  Uses Wininet API 
// program takes 1 mandatory command line argument - URL string 
// it downloads ito the current directory, or whatever is passed 
// as the second parameter to DownloadURLImage. 
// optional parameter, the name of the file (excluding path), by default it uses the 
// filename from the URL string. 

#include "stdafx.h" 
#include <iostream> 
#include <windows.h> 
#include <WinInet.h> // from SDK 
#include "string.h" 
//#include<TCHAR.H> 
//#include "Tchar.h" 
using namespace std ; 

int convertURLtofname (TCHAR * szURL, TCHAR * szname) 
// extract the filename from the URL 
{ 
    char aszfilename [100]; 
    HRESULT result; 
    char achar[3], aszURL [100]; 
    size_t nchars, i, j; 
    int fresult; 

    fresult = 0; 

    nchars= _tcslen(szURL); 
    i= nchars -1; 
    while ((i > 0) && (szURL[i] != '/') && (szURL[i] != '\\')) {i--;} 
    j= 0; i++; 
    while (i < nchars) { szname [j++]= szURL[i++]; } 
    szname[j]=_T('\0'); 

// wcstombs (aszfilename, szname, 100); 
//  cout << aszfilename << endl; 
//---------------------------------------------- 
    return fresult ; 
} 

int determinepathfilename (TCHAR * szURL, TCHAR * szpath, TCHAR * szname, TCHAR * szpathfilename) 
{ 
// use path and filename when supplied. If filename (e.g. funkypic.jpg) is not supplied, then the 
// filename will be extracted from the last part of the URL 
    int result ; 
    result= 0; 
    TCHAR szname_copy [100] ; 

     if ((szname == NULL) || (szname[0] == '\0')) 
      convertURLtofname (szURL, szname_copy); 
     else 
      _tcscpy (szname_copy, szname); 

     if ((szpath == NULL) || (szpath[0] == '\0')) 
       _tcscpy (szpathfilename, szname_copy); 
     else 
     { 
      _tcscpy (szpathfilename, szpath); 
      _tcscat (szpathfilename, szname_copy); 
     } 
    return result ; 
} 

bool GetFile (HINTERNET hOpen, // Handle from InternetOpen() 
        TCHAR *szURL,  // Full URL 
        TCHAR * szpath, 
        TCHAR * szname) 
{ 
    DWORD dwSize; 
    TCHAR szHead[15]; 
    BYTE * szTemp[1024]; 
    HINTERNET hConnect; 
    FILE * pFile; 
    TCHAR szpathfilename [100] ; 

    szHead[0] = '\0'; 

    if (!(hConnect = InternetOpenUrl(hOpen, szURL, szHead, 15, INTERNET_FLAG_DONT_CACHE, 0))) 
    { 
     std::cout << "Error: InternetOpenUrl" << std::endl; 
     return 0; 
    } 

    determinepathfilename (szURL, szpath, szname, szpathfilename); 

    if (!(pFile = _tfopen (szpathfilename, _T("wb")))) 
    { 
     std::cerr << "Error _tfopen" << std::endl; 
     return false; 
    } 
    do 
    { 
     // Keep copying in 1024 bytes chunks, while file has any data left. 
     // Note: bigger buffer will greatly improve performance. 
     if (!InternetReadFile (hConnect, szTemp, 1024, &dwSize)) 
     { 
      fclose (pFile); 
      std::cerr << "Error InternetReadFile" << std::endl; 
      return FALSE; 
     } 
     if (!dwSize) 
      break; // Condition of dwSize=0 indicate EOF. Stop. 
     else 
      fwrite(szTemp, sizeof (BYTE), dwSize , pFile); 
    } // do 
    while (TRUE); 
    fflush (pFile); 
    fclose (pFile); 

    return TRUE; 
} 

int DownloadURLImage (TCHAR * szURL, TCHAR * szpath, TCHAR * szname) 
{ int result ; 

    HINTERNET hInternet; 

    result= 0; 

    hInternet= InternetOpen (_T("imaged"), 
           INTERNET_OPEN_TYPE_DIRECT, //__in DWORD dwAccessType 
           NULL,      //__in LPCTSTR lpszProxyName, 
           NULL,      //__in LPCTSTR lpszProxyBypass, 
           NULL      //_in DWORD dwFlags 
          ); 

    GetFile (hInternet, szURL, szpath, szname) ; 
    InternetCloseHandle(hInternet); 
    return result ; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    if (argc == 2) 
    { 
     DownloadURLImage (argv[1], NULL, NULL); 
     //DownloadURLImage (argv[1], _T"C:/", NULL); 
    } 
    else if (argc == 3) 
    { 
     DownloadURLImage (argv[1], NULL, argv[2]); 
     //DownloadURLImage (argv[1], _T"C:/", argv[2]); 
    } 
    else 
    { 
     cout << "Usage: imaged <image URL>" << endl ; 
    } 
    system("pause") ; 
    return 0; 
} 
+0

Buen ejemplo. Parece que se necesita una corrección en la función GetFile(). BYTE * szTemp [1024]; debe ser BYTE szTemp [1024]; en lugar. szTemp debe ser una matriz de bytes y no una matriz de punteros de bytes. –

2

Si desea una solución fácil y no se preocupan por la seguridad, utilice este sorprendentemente simple chiste:

system("C:\\Users\\Me\\Desktop\\wget.exe http://pixelcaster.com/yosemite/webcams/ahwahnee2.jpg -O C:\\Users\\Me\\Desktop\\ahwahnee2.jpg"); 

Con wget para las ventanas

choco install wget 

Ver chocolatey.org

Cuestiones relacionadas