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
#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
#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。 (即使没有,也可以使用这些资源;你可以在那里查看它是如何实现的。)
#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。 :-)