InternetSetFilePointer -> wie mach ich das ?
-
wieso unprofessionell?
-
na ja... weil das das net wirklich einschränkt, ich will ja eine genaue angabe machen wie maximal 20kb/s oder so
Tim
-
wieso nicht, du kannst doch z.B. ein 5 KB packet laden, und wenn dann 1/4s noch nicht rum ist wartest du entsprechend
-
ok, aber nun zum topic zurück:
das mit resume geht doch net:
der code:Form1->fFile = fopen(Form1->Edit2->Text.c_str(), "a+"); // wb+ Form1->curpos = ftell(Form1->fFile); fseek(Form1->fFile, 0L, SEEK_END); Form1->length = ftell(Form1->fFile); fseek(Form1->fFile, Form1->curpos, SEEK_SET); for (int f = 0;f < 5;f++) { HttpQueryInfo(Form1->hFile, HTTP_QUERY_CONTENT_LENGTH, (LPVOID)Form1->lpszFileSize, &Form1->dwDummy, NULL); Form1->Label2->Caption = atoi(Form1->lpszFileSize); Form1->ProgressBar1->Max = atoi(Form1->lpszFileSize); Form1->ProgressBar1->Position = 0; //atoi(Form1->lpszFileSize) if(atoi(Form1->lpszFileSize) != 0) { /* MessageBox(NULL, "The file you want to download doesn't exist\nor has file size zero", "ERROR", MB_OK|MB_ICONERROR); InternetCloseHandle(Form1->hFile); InternetCloseHandle(Form1->hInternet); return 0; */ f = 6; } } if(atoi(Form1->lpszFileSize) == 0) { MessageBox(NULL, "The file you want to download doesn't exist\nor has file size zero", "ERROR", MB_OK|MB_ICONERROR); InternetCloseHandle(Form1->hFile); InternetCloseHandle(Form1->hInternet); return 0; } Form1->Button1->Caption = Form1->length; Form1->bGO = true; while(Form1->bGO) { if (Form1->length != 0) { InternetSetFilePointer(Form1->hFile,Form1->length,0,FILE_CURRENT,0); } Form1->bei++; Form1->bGO = InternetReadFile( Form1->hFile, &Form1->szBuf, 512, &Form1->ReadSize); Form1->Label1->Caption = Form1->bei * 1024 / 2 + Form1->grosse * sizeof(Form1->buf); Form1->ProgressBar1->Position = Form1->bei * 1024 / 2 + Form1->grosse * sizeof(Form1->buf); Application->ProcessMessages(); if(Form1->bGO && Form1->ReadSize == 0) break; Form1->szBuf[Form1->ReadSize] = '\0'; fwrite(&Form1->szBuf, 1, Form1->ReadSize, Form1->fFile); } fclose(Form1->fFile); InternetCloseHandle(Form1->hFile); InternetCloseHandle(Form1->hInternet);
ich hoffe, ihr könnt helfen
Tim
-
Ohne jetzt den Code groß angeschaut zu haben: was geht denn nicht?
-
na ja... er lädt was runter, aber die datei stimmt dann nicht (zu klein)
Tim
-
könntest du den Code vielleicht etwas kürzen und das rauslassen, was eh nichts damit zu tun hat
-
na ja... weiter kürzen wäre dumm... eigentlich gehört der ganze quellcode dazu
und vielleicht liegt der fehler ja da
Also, der Fehler ist, dass beim Resume eigentlich gar nichts runtergeladen wird....
Tim
-
Ok, ich hab den Fehler:
das
InternetSetFilePointer(Form1->hFile,Form1->length,0,FILE_CURRENT,0);
darf nicht in der While-Schleife stehen, sondern davor
Tim
-
ok,
1 Problem:
Wenn man SetInternetFilePointer ausführt, dann ist das kein wirkliches Resume, da er die Datei bis zu der angegebenen Position erstmal temporär herunterlädt und dann ab der angegebenen Position die Daten in der angegebenen Datei speichertwisst ihr, was das Problem ist
Tim
-
ok, selbst ist der Mann
es funktioniert
Hier nochmal der Code:
/* ein paar Einstellungen: */ Form1->bei = 0; Form1->Button1->Caption = "Abbrechen"; Form1->ProgressBar1->Position = 0; Form1->ProgressBar1->Max = 1; Form1->length = 0; Form1->hInternet = InternetOpen("Autoupdater->Test",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0); // Verbindung zum Internet herstellen if(!Form1->hInternet) // prüfen, ob im Internet -> wenn nicht, dann beenden { Application->MessageBox("Kein Internet.","Fehler",16); Form1->Button1->Caption = "Download"; Form1->CheckBox1->Enabled = true; if (Form1->CheckBox1->Checked == true) Form1->Edit3->Enabled = true; return 0; } if (Form1->resume == false) // schauen, ob resume oder nicht und je nach dem unterschiedliche Flags setzen { Form1->hFile = InternetOpenUrl(Form1->hInternet,Form1->Edit1->Text.c_str(),NULL,0,INTERNET_FLAG_RELOAD,0); // Link öffnen, der in Edit1 steht } else { Form1->hFile = InternetOpenUrl(Form1->hInternet,Form1->Edit1->Text.c_str(),NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0); // Link öffnen, der in Edit1 steht } if(!Form1->hFile) // prüfen, ob Datei existiert -> wenn nicht, dann beenden { Application->MessageBox("Keine Datei gefunden.","Fehler",16); InternetCloseHandle(Form1->hInternet); Form1->Button1->Caption = "Download"; Form1->CheckBox1->Enabled = true; if (Form1->CheckBox1->Checked == true) Form1->Edit3->Enabled = true; return 0; } for (int f = 0;f < 5;f++) { /* das ganze 5 mal versuchen, da man die Größe nicht immer beim ersten mal bekommt */ if (String(HttpQueryInfo(Form1->hFile, HTTP_QUERY_CONTENT_LENGTH, (LPVOID)Form1->lpszFileSize, &Form1->dwDummy, NULL)) == "1") // Größe der Datei im Internet auslesen { Form1->ProgressBar1->Max = atoi(Form1->lpszFileSize); Form1->ProgressBar1->Position = 0; if(atoi(Form1->lpszFileSize) != 0) // wenn wir die Größe haben, dann aus der for schleife raus { f = 6; } } } if(atoi(Form1->lpszFileSize) == 0) // wenn man die Größe nicht herausbekommen hat, dann beenden { MessageBox(NULL, "Die Datei existiert nicht oder hat die Größe 0.","Fehler", MB_OK|MB_ICONERROR); InternetCloseHandle(Form1->hFile); InternetCloseHandle(Form1->hInternet); Form1->Button1->Caption = "Download"; Form1->CheckBox1->Enabled = true; if (Form1->CheckBox1->Checked == true) Form1->Edit3->Enabled = true; return 0; } if (Form1->resume == false) // schauen, ob man Resumen will { Form1->fFile = fopen(Form1->Edit2->Text.c_str(), "wb+"); // Die Datei, die in Edit2 steht öffnen } else { Form1->fFile = fopen(Form1->Edit2->Text.c_str(), "ab+"); // Datei öffnen, die in Edit2 steht Form1->curpos = ftell(Form1->fFile); // fseek(Form1->fFile, 0L, SEEK_END); // Größe (in Bytes) der Datei in Edit2 herausfinden, für Resume Form1->length = ftell(Form1->fFile); // fseek(Form1->fFile, Form1->curpos, SEEK_SET); // } Form1->bGO = true; if (Form1->resume == true) { InternetSetFilePointer(Form1->hFile,Form1->length,0,FILE_CURRENT,0); // wenn resumet wird, zeiger auf die stelle setzen, wie groß die schon heruntergeladene Datei ist //Application->MessageBox("nach InternetSetFilePointer","a",0); } Form1->anzahl_runtergeladen = 0; LARGE_INTEGER ilPerfFreq; // QueryPerformanceFrequency(&ilPerfFreq); // Stoppuhr für Resume starten LARGE_INTEGER ilStartTime; // QueryPerformanceCounter(&ilStartTime); // while((Form1->bGO) && (Form1->beenden == false)) // solange man nicht die Datei heruntergeladen hat und nicht beendet wurde { if (((double(double(StrToInt(Form1->Edit3->Text)) * double(1024) / double(5))) >= double(Form1->anzahl_runtergeladen)) || (Form1->CheckBox1->Checked == false)) /* Wenn Limit eingestellt, dann: - 1sekunde in 5 teile teilen: dann ausrechnen, wie viel bytes man in einem der 5 teile einer sekunde herunterladen kann wenn man schon zu viel heruntergeladen hat, wird nichts weiter heruntergeladen wenn man weniger hat, wird weiter runtergeladen */ { Form1->bei++; // wie viel durchgänge man insgesamt hat wird erhöht //Application->MessageBox("davor","a",0); Form1->bGO = InternetReadFile(Form1->hFile,&Form1->szBuf,Form1->bytes_lesen,&Form1->ReadSize); // es wird die datei im internet gelesen und bytes_lesen bytes werden heruntergeladen //Application->MessageBox("gelesen","a",0); Form1->ProgressBar1->Position = double(Form1->bei * Form1->bytes_lesen) + Form1->length; // Form1->Label6->Caption = FloatToStrF(((double((double(Form1->bei * Form1->bytes_lesen + Form1->length) * 100) / atoi(Form1->lpszFileSize)))),ffNumber,3,0) + " %"; // ProgressBar und Prozentanzeige updaten if (((double((double(Form1->bei * Form1->bytes_lesen + Form1->length) * 100) / atoi(Form1->lpszFileSize)))) > double(100.0)) { Form1->Label6->Caption = "100 %";} // Application->ProcessMessages(); if(Form1->bGO && Form1->ReadSize == 0) break; // Form1->szBuf[Form1->ReadSize] = '\0'; // fwrite(&Form1->szBuf, 1, Form1->ReadSize, Form1->fFile); // heruntergeladene Bytes in die Datei schreiben Form1->anzahl_runtergeladen = Form1->anzahl_runtergeladen + Form1->bytes_lesen; // anzahl_heruntergeladen um bytes_lesen erhöhen, für Limit } else // wenn man schon zu viel heruntergeladen hat: { QueryPerformanceCounter(&Form1->ilCurrentTime); double dlTimeElapsed = (long double)(Form1->ilCurrentTime.QuadPart - Form1->ilStartTime.QuadPart)/((long double)Form1->ilPerfFreq.QuadPart); Sleep(double((double(1) / double(5)) - double(dlTimeElapsed)) * double(1000)); // schauen, wie lange es noch dauert, bis der eine teil der sekunde um ist und solange sleep } if (Form1->CheckBox1->Checked == true) // wenn ein limit eingestellt { QueryPerformanceCounter(&Form1->ilCurrentTime); double dlTimeElapsed = (long double)(Form1->ilCurrentTime.QuadPart - Form1->ilStartTime.QuadPart)/((long double)Form1->ilPerfFreq.QuadPart); if (dlTimeElapsed * 5 >= 1) // wenn ein Teil der Sekunde erreicht wurde: { Form1->anzahl_runtergeladen = 0; // anzahl_heruntergeladen wieder auf 0 setzen QueryPerformanceFrequency(&Form1->ilPerfFreq); QueryPerformanceCounter(&Form1->ilStartTime); } } } fclose(Form1->fFile); // InternetCloseHandle(Form1->hFile); // Datei und Internet schließen InternetCloseHandle(Form1->hInternet); //
ein paar Worte dazu:
in Edit1 steht der InternetURL
in Edit2 steht der URL, wohin die Datei geladen werden soll
in Edit3 steht das Limit in kb/s, wenn CheckBox1->Checked = true<--- da sieht man bestimmt nicht durch
Der Fehler war, dass beim Resume bei InternetOpenURL eine andere Flag gesetzt werden musste
Tim
P.S.
vielleicht kann man das ja zu dem FAQ hinzufügen :p
P.P.S.
ich habe das an B&M Raid geschickt (die Seite kennen bestimmt einige hier)
da wird das dann, denke ich, auch zu sehen seinTim
-
Was hat eine reine (und damit umständliche) WinAPI-Lösung bei B&M zu suchen, wenn man das Ganze z.B. mit den Indy-Komponenten in echter RAD-Manier viel einfacher lösen kann?
-
ich finde komponenten manchmal einfach nur Sche***, da kann man nicht immer das machen, was gemacht werden soll
Tim
-
Nicht immer, aber meistens.
Ich hab mir grad ein PAP zusammengekritzelt, vielleicht mach ich morgen mal ein Beispiel mit der Indy-Kompo fertig.