How to get the file size before downloading - c++

I am trying to download a binary file from a http: server. I am using the functions InternetOpenUrl() and then InternetReadFile() to download the file. Is it possible to know the size of the file before downloading?.
Thanks
Vinod

You can use HttpQueryInfo() with HTTP_QUERY_CONTENT_LENGTH for this, although the server is not required to send the content length and so you should not rely on this.

You might want to call InternetGetLastResponseInfo after the call to InternetOpenUrl to get the response headers. Those should (most likely) contain the content-length of the file.

Related

C++ WinINet InternetReadFile function refresh

I am trying to get the content of a file using WinHTTP in C++. The file is a XML File and is generated by a executable on a server.
The code for init, connect and even read a file on the specified server address is working.
// Connect to internet.
m_hInternet = InternetOpen(L"HTTPRIP",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
// Check if worked.
if( !m_hInternet )
return;
// Connect to selected URL.
m_hUrl = InternetOpenUrlA(m_hInternet, strUrl.c_str(), NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RESYNCHRONIZE, 0);
// Check if worked.
if( !m_hUrl )
return;
if( InternetReadFile(m_hUrl, buf, BUFFER_SIZE, &bytesread) && bytesread != 0 )
{
// Put into std::string.
strData = std::string(buf,buf+bytesread);
}
Now I want to update the file (same address). The server update the file at 50Hz and I want my code to be able to ReadFile only if it has been updated by the server. Can InternetReadFile do that kind of thing? Maybe with a FLAG but I didn't find a thing on MSDN.
Thanks for your help.
There is no way in the HTTP protocol for you directly do that, hence there is no such function in WinHTTP. The easiest solution might be to download the file and see if it's changed, if the file is relatively small, or if the file is large, let the server which writes the file, also write a timestamp, checksum or counter increment file next to it.
Then your code would download the checksum file, see if it's changed, and in that case download the original file.
Or another solution would be to put a timestamp or similar data in the beginning of the XML file, and stop downloading the file if the timestamp (or checksum) is not updated. (This comes with its own drawbacks of course, you may have to write your own parser.)
If HTTP server has a page with info (e.g. timestamp) on this file (no matters that a file is generated; the page may be generated too), you may examine this page.
As you know that server updates the file with (nearly) constant speed, your app may just use the timer.
P.S. I doubt if there's really a sense in reading some file 50 times every second.

How to read metafiles of NTFS file system using C

Can anyone show me how to directly access metafiles ($MFT, $Volume, $Bitmap...) ?
I need to get info from these files.
You can use the ioctl function, FSCTL_GET_NTFS_FILE_RECORD.

PDF download corrupted / HTTP header problems

I have some legacy code in one of application which is used for PDF file download (PDF file is around 350-400KB size) and recently we had complains (from around 1% customers) saying PDF download is failing with damaged/corrupted file errors.
Here is snippet of code (C++ application) setting headers for download
String header;
header.append("Content-type: application/force-download\r\n");
header.append("Content-Transfer-Encoding: Binary\r\n");
header.append("Content-length: %d\r\n", filebuf.length());
header.append("Connection: Close\r\n");
header.append("Content-disposition: attachment; filename=%s\r\n\r\n", filename_to_download.chars());
String class and append method is just for an example.
I understand above headers are not the best way to trigger PDF file download (I've simplified headers by having "Content-Type application/octet-stream and Content-Disposition : attachment; filename=example.pdf" and seems like its working for me).
But I am not able to understand why above original code should not work 1% of time.
I was trying to understand browser/adobe combination but seems there is no pattern here, YES one thing few of customers mentioned is when they changed to "chrome browser" it worked most of the times.
Any pointers?
After couple of days of struggle finally figured out whats happening in here.
We are setting content length as size of buffer (pdf file size) in header from our code and sending this data to client but in-between apache module mod_gzip/mod_deflate is compressing data buffer and what reaches client/browser is "Content-Length: 100 bytes" but actual data is say 60-70 bytes.
Not every browser complains about this mismatch but certain browsers treats this as FATAL error and shows message "couldn't download file" (we've seen this issue frequently in Win8/IE10 and Win8/IE11, there could be some other security settings too causing this on browser!).
For the fix, we've removed "Content-Length" from header.

How to get the length of a file without downloading the file in a cURL binary get request

I want to create a cURL request in some C++ code which will get me the length of a file in a server without downloading the file. For that, I use some cURL options to tell I only want headers in the request response, and then I examine the response to get the file length.
I'm setting the following request options:
curl_easy_setopt(_curl_handle, CURLOPT_HEADER, 1);
curl_easy_setopt(_curl_handle, CURLOPT_NOBODY, 1);
Then processing the request, waiting for the response, which shows a OK=200, and finally enquiring about the file length:
curl_easy_getinfo(_curl_handle, CURLINFO_CONTENT_LENGTH_UPLOAD, &dResult);
But I get a file length of -1. According to cURL documentation, that means size is unknown. How can it happen that cURL doesn't get the file length information from the server?
CURLINFO_CONTENT_LENGTH_UPLOAD is the number of bytes uploaded. You need to use CURLINFO_CONTENT_LENGTH_DOWNLOAD instead.
Note that if the server dynamically generates the data, the length may be different when you actualy download the file versus just downloading its headers.
Also note that if the server sends data as compressed when downloaded, there may not be any size available in the headers (if the Transfer-Encoding header is used instead of the Content-Length header), so CURLINFO_CONTENT_LENGTH_DOWNLOAD would still return -1. The only way to know the size in that situation would be to download it in full.
Have you tried with CURLINFO_CONTENT_LENGTH_DOWNLOAD instead?
need call perform()
curl_easy_setopt(_curl_handle, CURLOPT_HEADER, 1);
curl_easy_setopt(_curl_handle, CURLOPT_NOBODY, 1);
curl_easy_perform(_curl_handle);
curl_easy_getinfo(_curl_handle, CURLINFO_CONTENT_LENGTH_UPLOAD,
&dResult);

Edit the frame rate of an avi file

Is it possible to change the frame rate of an avi file using the Video for windows library? I tried the following steps but did not succeed.
AviFileInit
AviFileOpen(OF_READWRITE)
pavi1 = AviFileGetStream
avi_info = AviStreamInfo
avi_info.dwrate = 15
EditStreamSetInfo(dwrate) returns -2147467262.
I'm pretty sure the AVIFile* APIs don't support this. (Disclaimer: I was the one who defined those APIs, but it was over 15 years ago...)
You can't just call EditStreamSetInfo on an plain AVIStream, only one returned from CreateEditableStream.
You could use AVISave, then, but that would obviously re-copy the whole file.
So, yes, you would probably want to do this by parsing the AVI file header enough to find the one DWORD you want to change. There are lots of documents on the RIFF and AVI file formats out there, such as http://www.opennet.ru/docs/formats/avi.txt.
I don't know anything about VfW, but you could always try hex-editing the file. The framerate is probably a field somewhere in the header of the AVI file.
Otherwise, you can script some tool like mencoder[1] to copy the stream to a new file under a different framerate.
[1] http://www.mplayerhq.hu/
HRESULT: 0x80004002 (2147500034)
Name: E_NOINTERFACE
Description: The requested COM interface is not available
Severity code: Failed
Facility Code: FACILITY_NULL (0)
Error Code: 0x4002 (16386)
Does it work if you DON'T call EditStreamSetInfo?
Can you post up the code you use to set the stream info?