comparison ui/downloader_win.cpp @ 17:c12825a651ed

Read out content-length and use this to skip existing files
author Andre Heinecke <aheinecke@intevation.de>
date Wed, 19 Feb 2014 14:22:26 +0000
parents 95e1b6edf2fc
children f4f957c58e0a
comparison
equal deleted inserted replaced
16:225a5ec20dad 17:c12825a651ed
19 #include <winhttp.h> 19 #include <winhttp.h>
20 20
21 #include <QDebug> 21 #include <QDebug>
22 #include <QDateTime> 22 #include <QDateTime>
23 #include <QSaveFile> 23 #include <QSaveFile>
24 #include <QFileInfo>
24 25
25 #define DEBUG if (1) qDebug() << __PRETTY_FUNCTION__ 26 #define DEBUG if (1) qDebug() << __PRETTY_FUNCTION__
26 27
27 #define MAX_SW_SIZE 10485760 28 #define MAX_SW_SIZE 10485760
28 #define MAX_LIST_SIZE 1048576 29 #define MAX_LIST_SIZE 1048576
30
31
32 #define LIST_RESOURCE "/incoming/aheinecke/test"
33 #define SW_RESOURCE "/incoming/aheinecke/test"
34
29 35
30 /** @brief Qt wrapper around FormatMessage 36 /** @brief Qt wrapper around FormatMessage
31 * 37 *
32 * @returns The error message of the error that occurred 38 * @returns The error message of the error that occurred
33 */ 39 */
279 SetLastError(err); 285 SetLastError(err);
280 return retval; 286 return retval;
281 } 287 }
282 288
283 bool Downloader::downloadFile(HINTERNET hSession, HINTERNET hConnect, 289 bool Downloader::downloadFile(HINTERNET hSession, HINTERNET hConnect,
284 LPCWSTR resource, const QString &filename, DWORD maxSize) 290 LPCWSTR resource, const QString &fileName, DWORD maxSize)
285 { 291 {
286 HINTERNET hRequest = NULL; 292 HINTERNET hRequest = NULL;
287 bool retval = false; 293 bool retval = false;
288 DWORD bytesAvailable = 0, 294 DWORD bytesAvailable = 0,
289 err = 0, 295 err = 0,
290 bytesRead = 0, 296 bytesRead = 0,
291 totalDownloaded = 0; 297 totalDownloaded = 0,
292 298 contentLength = 0,
293 QSaveFile outputFile(filename); 299 sizeOfDWORD = sizeof (DWORD);
300
301 QSaveFile outputFile(fileName);
294 302
295 if (!hSession || !hConnect || !resource) { 303 if (!hSession || !hConnect || !resource) {
296 SetLastError(ERROR_INVALID_PARAMETER); 304 SetLastError(ERROR_INVALID_PARAMETER);
297 return retval; 305 return retval;
298 } 306 }
320 if (!verifyCertificate(hRequest)) { 328 if (!verifyCertificate(hRequest)) {
321 DEBUG << "Certificate verification failed"; 329 DEBUG << "Certificate verification failed";
322 // TODO error out 330 // TODO error out
323 } 331 }
324 332
333
334 if (!(WinHttpQueryHeaders(hRequest,
335 WINHTTP_QUERY_CONTENT_LENGTH |
336 WINHTTP_QUERY_FLAG_NUMBER,
337 NULL,
338 &contentLength,
339 &sizeOfDWORD,
340 WINHTTP_NO_HEADER_INDEX))) {
341 // Continue anyway as we later really check how
342 // much we download.
343 DEBUG << "No content-length";
344 }
345
346 if (contentLength > maxSize) {
347 err = ERROR_INVALID_DATA;
348 goto cleanup;
349 }
350
351 if (contentLength) {
352 QFileInfo finf(fileName);
353 if (finf.exists() && finf.isReadable() &&
354 finf.size() == contentLength) {
355 // We already have data of the same size
356 // No need to waste bandwidth.
357 DEBUG << "Skipping download because file exists";
358 retval = true;
359 goto cleanup;
360 }
361 }
362
325 // Open / Create the file to write to. 363 // Open / Create the file to write to.
326 if (!outputFile.open(QIODevice::WriteOnly)) { 364 if (!outputFile.open(QIODevice::WriteOnly)) {
327 DEBUG << "Failed to open file"; 365 DEBUG << "Failed to open file";
328 err = GetLastError(); 366 err = GetLastError();
329 goto cleanup; 367 goto cleanup;
330 } 368 }
331 369
370 DEBUG << "output file size: " << outputFile.size();
332 do 371 do
333 { 372 {
334 char outBuf[8192]; // 8KB is the internal buffer size of winhttp 373 char outBuf[8192]; // 8KB is the internal buffer size of winhttp
335 memset(outBuf, 0, sizeof(outBuf)); 374 memset(outBuf, 0, sizeof(outBuf));
336 bytesRead = 0; 375 bytesRead = 0;
348 } 387 }
349 388
350 if (bytesAvailable > maxSize) { 389 if (bytesAvailable > maxSize) {
351 DEBUG << "File to large"; 390 DEBUG << "File to large";
352 retval = false; 391 retval = false;
392 err = ERROR_INVALID_DATA;
353 break; 393 break;
354 } 394 }
355 395
356 if (!WinHttpReadData(hRequest, (LPVOID)outBuf, 396 if (!WinHttpReadData(hRequest, (LPVOID)outBuf,
357 sizeof(outBuf), &bytesRead)) { 397 sizeof(outBuf), &bytesRead)) {
358 DEBUG << "Error reading data"; 398 DEBUG << "Error reading data";
359 err = GetLastError(); 399 err = GetLastError();
360 break; 400 break;
361 } else { 401 } else {
362 if (bytesRead) { 402 if (bytesRead) {
363 DEBUG << "Downloaded: " << bytesRead << "B";
364
365 // Write data to file. 403 // Write data to file.
366 if (outputFile.write(outBuf, bytesRead) != 404 if (outputFile.write(outBuf, bytesRead) !=
367 bytesRead) { 405 bytesRead) {
368 err = GetLastError(); 406 err = GetLastError();
369 DEBUG << "Error writing to file."; 407 DEBUG << "Error writing to file.";
390 } 428 }
391 } while (bytesAvailable > 0); 429 } while (bytesAvailable > 0);
392 430
393 cleanup: 431 cleanup:
394 432
395 if (retval) { 433 if (retval && outputFile.isOpen()) {
396 // Actually save the file to disk / move to homedir 434 // Actually save the file to disk / move to homedir
397 retval = outputFile.commit(); 435 retval = outputFile.commit();
398 } 436 }
399 437
400 if (hRequest) { 438 if (hRequest) {
438 goto cleanup; 476 goto cleanup;
439 } 477 }
440 478
441 479
442 lastModifiedSoftware = getLastModifiedHeader(hSession, hConnect, 480 lastModifiedSoftware = getLastModifiedHeader(hSession, hConnect,
443 L"/incoming/aheinecke/test"); 481 L""SW_RESOURCE);
444 482
445 lastModifiedList = getLastModifiedHeader(hSession, hConnect, 483 lastModifiedList = getLastModifiedHeader(hSession, hConnect,
446 L"/incoming/aheinecke/test"); 484 L""LIST_RESOURCE);
447 485
448 if (!lastModifiedList.isValid() || !lastModifiedSoftware.isValid()) { 486 if (!lastModifiedList.isValid() || !lastModifiedSoftware.isValid()) {
449 DEBUG << "Could not read headers: " << getLastErrorMsg(); 487 DEBUG << "Could not read headers: " << getLastErrorMsg();
450 goto cleanup; 488 goto cleanup;
451 } 489 }
460 498
461 QString fileName = dataDirectory.append("/SW-") 499 QString fileName = dataDirectory.append("/SW-")
462 .append(lastModifiedSoftware.toString("yyyymmddHHmmss")) 500 .append(lastModifiedSoftware.toString("yyyymmddHHmmss"))
463 .append(".exe"); 501 .append(".exe");
464 502
465 DEBUG << "Filename: " << fileName; 503 DEBUG << "fileName: " << fileName;
466 504
467 if (!downloadFile(hSession, hConnect, L"/incoming/aheinecke/test", 505 if (!downloadFile(hSession, hConnect, L""SW_RESOURCE,
468 fileName, MAX_SW_SIZE)) { 506 fileName, MAX_SW_SIZE)) {
469 DEBUG << "Error downloading File: " << getLastErrorMsg(); 507 DEBUG << "Error downloading File: " << getLastErrorMsg();
470 goto cleanup; 508 goto cleanup;
471 } 509 }
472 510
481 519
482 QString fileName = dataDirectory.append("/list-") 520 QString fileName = dataDirectory.append("/list-")
483 .append(lastModifiedSoftware.toString("yyyymmddHHmmss")) 521 .append(lastModifiedSoftware.toString("yyyymmddHHmmss"))
484 .append(".txt"); 522 .append(".txt");
485 523
486 DEBUG << "Filename: " << fileName; 524 DEBUG << "fileName: " << fileName;
487 525
488 if (!downloadFile(hSession, hConnect, L"/incoming/aheinecke/test", 526 if (!downloadFile(hSession, hConnect, L""LIST_RESOURCE,
489 fileName, MAX_LIST_SIZE)) { 527 fileName, MAX_LIST_SIZE)) {
490 DEBUG << "Error downloading File: " << getLastErrorMsg(); 528 DEBUG << "Error downloading File: " << getLastErrorMsg();
491 goto cleanup; 529 goto cleanup;
492 } 530 }
493 531

http://wald.intevation.org/projects/trustbridge/