如何将图像从URL下载到本地目录?

时间:2021-04-28 16:49:34

I'm using C++ without .NET on Win32, how can I download an image over HTTP from a website without having to re-invent the wheel? Is there an API or library that provides a single function to do this?

我在Win32上使用不带.NET的C ++,如何从网站上通过HTTP下载图像而无需重新发明*?是否有提供单一功能的API或库来执行此操作?

http://mywebsite/file.imgext --> C:\path\to\dir\file.imgext

http://mywebsite/file.imgext - > C:\ path \ to \ dir \ file.imgext

7 个解决方案

#1


You could use cURLpp

你可以使用cURLpp

I havn't used it yet, but example20 looks like it could solve your problem.

我还没有使用它,但是example20看起来可以解决你的问题。

#2


WinInet APIs are easier than you think

WinInet API比您想象的要容易

Here is a complete win32 console program. Can be built with with VS 2010 Express and down loading windows SDK to get WinInit.

这是一个完整的win32控制台程序。可以使用VS 2010 Express和下载Windows SDK构建以获取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;
}

#3


If you want an EASY solution, use this amazingly simple one liner:

如果您想要一个简单的解决方案,请使用这个非常简单的一个衬垫:

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

With wget for windows

用wget for windows

choco install wget

See chocolatey.org

#4


Use Windows Http Services API.

使用Windows Http Services API。

#5


You could use the WinInet or WinHTTP classes in C++. These are native Win32 APIs the abstract some of the work of getting sending and receiving files from the Internet.

您可以在C ++中使用WinInet或WinHTTP类。这些是本机Win32 API,它是从Internet发送和接收文件的一些工作的摘要。

I've used WinInet with great success to do just what you're trying to do.

我已经使用WinInet取得了巨大的成功,可以完成你想要做的事情。

#6


If starting a new process is ok, you could have a look at WGET. (And even if not, the sources are available; you can look there to see how it's been implemented.)

如果开始一个新的过程是好的,你可以看看WGET。 (即使没有,也可以使用这些资源;你可以在那里查看它是如何实现的。)

#7


Using POCO for this now. :-)

现在使用POCO。 :-)

#1


You could use cURLpp

你可以使用cURLpp

I havn't used it yet, but example20 looks like it could solve your problem.

我还没有使用它,但是example20看起来可以解决你的问题。

#2


WinInet APIs are easier than you think

WinInet API比您想象的要容易

Here is a complete win32 console program. Can be built with with VS 2010 Express and down loading windows SDK to get WinInit.

这是一个完整的win32控制台程序。可以使用VS 2010 Express和下载Windows SDK构建以获取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;
}

#3


If you want an EASY solution, use this amazingly simple one liner:

如果您想要一个简单的解决方案,请使用这个非常简单的一个衬垫:

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

With wget for windows

用wget for windows

choco install wget

See chocolatey.org

#4


Use Windows Http Services API.

使用Windows Http Services API。

#5


You could use the WinInet or WinHTTP classes in C++. These are native Win32 APIs the abstract some of the work of getting sending and receiving files from the Internet.

您可以在C ++中使用WinInet或WinHTTP类。这些是本机Win32 API,它是从Internet发送和接收文件的一些工作的摘要。

I've used WinInet with great success to do just what you're trying to do.

我已经使用WinInet取得了巨大的成功,可以完成你想要做的事情。

#6


If starting a new process is ok, you could have a look at WGET. (And even if not, the sources are available; you can look there to see how it's been implemented.)

如果开始一个新的过程是好的,你可以看看WGET。 (即使没有,也可以使用这些资源;你可以在那里查看它是如何实现的。)

#7


Using POCO for this now. :-)

现在使用POCO。 :-)