Dateidownload von Download-URL + anschließendes Entpacken



  • Hallo,

    ich bin neu hier und hoffe, dass man mir hier weiterhelfen kann.
    Ich bin noch Anfänger, was das Programmieren angeht, versuche mich aber immer neuen Herausforderungen zu stellen und stehe nun vor einem Problem.
    Vielleicht sagt sich der ein oder andere, dass ich nicht sowas schwieriges machen soll aber dieses Thema interessiert mich derzeit brennend, weshalb ich jetzt nicht aufgeben möchte :).

    Ich versuche mich gerade an einem Programm, wo ich von einer Internetseite (legal) Zip Dateien mittels einer URL, welche sich in einer Textdatei bzw. Excel Tabelle befindet downloaden kann.

    Die entsprechenden URLs habe ich in dem Dokument untereinandergeschrieben.
    Die URLs beinhalten den direkten Link zur Datei.
    Wenn man diese händisch im Browser eintragen würde, würde sich direkt das Popup zum Speichern öffnen.

    Da die Dateien in ihrer Ursprungsform (also als Zip Datei) alle gleich benannt sind, wäre es sinnvoll die Dateien nacheinander zu downloaden und zunächst zu entpacken, da er dort enthaltene Ordner einen individuellen Namen hat.

    Ich komme allerdings schon mit dem Download der Dateien nicht klar.
    Ich habe im Internet etwas mit LPCWSTR gefunden und habe jetzt auch schon mehrfach herum probiert aber mein Visual Studio spuckt nur Fehler aus.

    Das hab ich im Ineternet gefunden und etwas abgeändert. Leider ohne erfolg!

    #include "stdafx.h"
    #include <iostream>
    #include "string"
    #include <fstream>
    #include <conio.h>
    #include <stdio.h>
    #include <urlmon.h>
    using namespace std;
    
    int main()
    {
    
                                   char zeile[200]; //zeile ist ein C-String
                                   fstream datei("C:\\Users\\Name\\Desktop\\test.txt", ios::in);
                                   char test[200] = "C:\\Users\\Name\\Desktop\\Test";
                                   LPCWSTR lpcwstr1 = (LPCWSTR)test;
                                   while (datei.getline(zeile, 200))
                                   {
                                                   LPCWSTR lpcwstr2 = (LPCWSTR) zeile;
                                                   cout << test << endl;
                                                   HRESULT hr = URLDownloadToFile(NULL, lpcwstr1, NULL, 0, NULL);
                                   }
    
                                   datei.close();
                                   system("Pause");
                                   return 0;
    }
    


  • Herzlich willkommen im Forum.

    Ich würde dir mal ein Blick in die libcurl empfehlen. Aber dein Ansatz über die Windows API sollte auch gehen, ist dann aber Plattform abhängig.

    Bei deiner Download Funktion fehlt der Pfad zu einer Datei in der der Download gespeichert werden soll.

    Der dritte Parameter ist:

    szFileName
    A pointer to a string value containing the name or full path of the file to create for the download. If szFileName includes a path, the target directory must already exist.

    So kann die Funktion die Datei nirgends speichern.

    Wenn du den Umweg über eine Datei nicht machen möchtest, ist vlt. URLOpenStream noch ein Blick wert.

    Über was beschwert sich visual studio denn?



  • Hey,

    danke für die Rückmeldung.

    Der DownloadPfad soll dieser hier sein.

    char test[200] = "C:\\Users\\Name\\Desktop\\Test";

    Er soll den Ordner also (im späteren Verlauf) selbst anlegen, falls dieser nicht vorhanden ist.
    Vielmehr möchte ich später versuchen das Download-Verzeichnis nur temporär zu erstellen.

    Visual Studio sagt beim ausführen des Codes "kann nicht ausgeführt werden - kann die angegebene Datei nicht finden (test.exe)"

    Sowas in die Richtung.

    EDIT:

    Habe jetzt zumindest keine Fehlermeldung mehr. Ausführung erfolgt problemlos aber es landet keine Datei im angegebenen Ordner. Es wird also nichts gedownloadet.

    // Test.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include "string"
    #include <fstream>
    #include <conio.h>
    #include <stdio.h>
    #include <urlmon.h>
    #pragma comment(lib, "urlmon.lib")
    using namespace std;
    
    int main()
    {
                    char zeile[200]; //zeile ist ein C-String
                    fstream datei("C:\\Users\\Name\\Desktop\\test.txt", ios::in);
                    //char test[200] = "C:\\Users\\Name\\Desktop\\Testdownload";
                    //LPCWSTR file = (LPCWSTR)test;
                    LPCWSTR file = (LPCWSTR)"C:\\Users\\Name\\Desktop\\Testdownload";
                    while (datei.getline(zeile, 200))
                    {
                                   LPCWSTR url = (LPCWSTR)zeile;
                                   cout << zeile << endl;
                                   HRESULT hr = URLDownloadToFile(NULL, url, file, 0, NULL);
                    }
    
                    datei.close();
                    system("Pause");
                    return 0;
    }
    


  • Ein weiteres Problem wird deine C-Style Konvertierung zwischen LPCWSTR und char[] sein. Wenn ich das auf die Schnelle richtig sehe ist LPCWSTR äquivalent zu wchar_t const *. Das ist so eine Windowseigenheit, dass hier mit Wide Strings gearbeitet wird.
    Versuch mal sowas:

    #include "stdafx.h"
    #include <iostream>
    #include "string"
    #include <fstream>
    #include <conio.h>
    #include <stdio.h>
    #include <urlmon.h>
    #pragma comment(lib, "urlmon.lib")
    using namespace std;
    
    int main()
    {
      wchar_t zeile[200]; //zeile ist ein C-String
      wfstream datei(L"C:\\Users\\Name\\Desktop\\test.txt", ios::in);
      LPCWSTR file = L"C:\\Users\\Name\\Desktop\\Testdownload";
      while (datei.getline(zeile, 200))
      {
         LPCWSTR url = zeile;
         wcout << zeile << endl;
         HRESULT hr = URLDownloadToFile(NULL, url, file, 0, NULL);
      }
      datei.close();
      system("Pause");
      return 0;
    }
    

    Hab ich jetzt nicht durch 'nen Compiler gejagt. Habe zuhause aktuell keine Windows Entwicklungsumgebung 😉

    Edit: die Datei sollte so natürlich in eine Datei namens Testdownload auf dem Desktop gespeichert werden und nicht in einen Ordner Testdownload 😉



  • Also das läuft super durch keine Fehler.

    Wenn der Ordner nicht vorhanden ist legt er einen neuen an aber er wird nicht wirklich als Ordner dargestellt, sondern als Datei, die ich nicht öffnen kann (muss dann ein Programm auswählen mit dem ich die Datei öffnen möchte).

    Wenn der Ordner vorhanden ist speichert er aber auch keine Dateien darin.
    In der Konsole wird allerdings angezeigt, dass er die Dateien nacheinander abarbeitet, das ist schon mal ziemlich cool.

    Danke schon mal dafür 🙂



  • Siehe mein Edit von oben. Wenn es eine Datei in dem Ordner sein soll, musst du sowas schreiben.:

    LPCWSTR file = L"C:\\Users\\Name\\Desktop\\Testdownload\\Datei.dat";
    


  • Achso bitte entschuldige. Habe ich wohl überlesen.

    Der Download in den entsprechenden Ordner funktioniert. Wenn ich die Datei als

    "Datei.dat oder z.B. als Datei.zip speichere" ist die Datei dann auch in diesem ZIP Ordner.

    Hatte jetzt gedacht nach dem "\\Testdownload\" hinter die \\ einfach gar nichts mehr hinzuschreiben, sodass die Datei direkt entpackt in den Ordner hineingeschrieben wird. Funktioniert nur leider nicht :D.

    Mir ist außerdem aufgefallen, dass er aus der URL.txt nur den letzten Eintrag liest und downloade statt alle URLs nacheinander auszulesen und zu downloaden.



  • URLDownloadToFileA
    wäre ein zu einfacher vorschlag gewesen 😮



  • xs4my schrieb:

    Achso bitte entschuldige. Habe ich wohl überlesen.

    Der Download in den entsprechenden Ordner funktioniert. Wenn ich die Datei als

    "Datei.dat oder z.B. als Datei.zip speichere" ist die Datei dann auch in diesem ZIP Ordner.

    Hatte jetzt gedacht nach dem "\\Testdownload\" hinter die \\ einfach gar nichts mehr hinzuschreiben, sodass die Datei direkt entpackt in den Ordner hineingeschrieben wird. Funktioniert nur leider nicht :D.

    Mir ist außerdem aufgefallen, dass er aus der URL.txt nur den letzten Eintrag liest und downloade statt alle URLs nacheinander auszulesen und zu downloaden.

    Nein, der Downloaded schon alle. Es wird halt nur immer die letzte Datei überschrieben, weil du immer den gleichen Datei Namen benutzt.



  • Achsoo.

    Dann muss ich, nachdem die erste Datei heruntergeladen wurde diese erst entpacken lassen und dann darf er erst mit der nächsten Datei fortfahren.

    EDIT:

    Bin schon wieder seit Stunden am Googlen. Ich habe herausgefunden, dass ich eine Libary einbinden muss, um die Dateien downloaden zu können.

    Hab es zuerst mit Zip Utils probiert. Da dort aber nicht viel beschrieben steht, blicke ich da nicht so ganz durch.
    Bin derzeit bei 7Zip angekommen dort gibt es ein LZMA SDK (Software Development Kit).

    Dies habe ich auch gedownloadet aber in dem Ordner sind so viele Dateien, dass ich nicht weiß, welche ich jetzt genau davon brauche.

    Ich möchte nur die Zip Dateien entpacken in den gleichen Ordner, wo die Zip Datei auch nach dem Download gespeichert wird also in dem Fall der Ordner "TestDownload".

    Bitte noch mal um Hilfe :(.



  • Mitt dem 7Zip sdk habe ich noch nichts gemacht. Ich hätte dir jetzt zu zlib geraten.
    http://www.zlib.net/zlib_how.html

    Da gib es ein entsprechendes Beispiel. Oder sonst findet man via Google dazu auch recht viel auf Stackoverflow.

    Du könntest auch erstmal alle Daten runter laden. Du müsstest halt den Dateinamen in jedem Schleifen Durchlauf ändern. Evt. abhängig von der URL, die sich ja jeweils unterscheiden muss.



  • Zlib habe ich auch gefunden die Datei von Zlip sieht aber ähnlich verwirrend aus.
    Ich finde nix halbes und nix ganzes wie man das ganze nutzt.

    Ist teilweise echt schwierig.
    Mein Fachenglisch ist jetzt auch nicht das beste. Klar muss ich hier noch üben aber das was ich so lese ist häufig nicht wirklich für Anfänger beschrieben.

    Wäre es zu viel verlangt wenn du mir da noch einmal helfen könntest :(?

    EDIT:

    Kann man sowas nicht anders lösen ich mein - Windows hat ja auch Boardmittel zum entpacken von Dateien? Das man irgendwie über eine Batch Datei oder so ähnlich die Dateien nach dem Download entpackt?



  • Viele Wege führen ans Ziel. Du kannst die Dateien auch erst runter laden und dann mit einem anderen Skript entpacken.

    Ich sitze wohl erst am Montag wieder vor nem Computer und via Smartphone kann und will ich das nicht erklären. Da tippe ich mich zu Tode und würde wahrscheinlich mehr Tippfehler einbauen als gut wäre.

    Wenn du es noch auf englisch probieren willst hier ist das noch mal ganz gut erklärt: http://stackoverflow.com/questions/4696907/zlib-c-and-extracting-files



  • Danke für die schnelle Rückmeldung.

    Ich habe vorhin das Manual und die FAQ Seite durchstöbert aber irgendwie blicke ich da einfach nicht durch.

    Ich habe auch schon versucht irgendwelche DLL Dateien von zlib und 7z einzubinden aber das hat kein Stück funktioniert.
    Außerdem kann man wohl über NET Framework ZIP oder so ähnlich die Dateien entpacken dazu müsste ich über Verweise in VS etwas einbinden aber dort werden mir keine Verweise angezeigt.

    Es ist echt frustrierend.

    Ich probiere zwar weiter und melde mich, falls ich was erreicht habe aber wenn es keine Umstände für Dich sind würde warte ich dann bis Montag auf deine Antwort.

    Den Link werde ich mir auch einmal versuchen durchzulesen.

    Vielen Dank!

    EDIT:

    Bin am überlegen das Ganze im Java zu programmieren, da mir die Sprache leichter als C++ erscheint. Bin mir nicht sicher, was du davon hälst.



  • Hi,

    ich habe mir ein paar Gedanken zu deinem "entpack-Problem" gemacht. Tatsächlich würde ich dir inzwischen davon abraten, direkt mit zlib zu arbeiten. Du solltest einen entsprechenden C++ Wrapper drum herum benutzen. Das hat den Vorteil, dass du dich auf C++ konzentrieren kannst und dich erstmal noch nicht mit C Code auseinander setzen musst, der dich wahrscheinlich mehr verwirrt, als hilfreich ist.

    Ich möchte dir an dieser Stelle gerne die Boost Bibliothek (http://www.boost.org/) ans Herzen legen. Für dein Problem, ist das zwar ein bisschen wie mit Kanonen auf Spatzen geschossen, aber wenn du C++ lernen willst, empfiehlt es sich, sich auch mal mit Boost auseinander zu setzen.
    Trotzdem musst du dir, um damit entpacken zu können, zlib installieren.

    Hier gibt es eine Anleitung zur Installation von Boost: http://www.boost.org/doc/libs/1_64_0/libs/iostreams/doc/installation.html Sry, wieder Englisch, aber das ist (leider) standard in der It Branche.
    Kurzversion:
    - Zlib herunter laden
    - In der Visual Studio Command Prompt zu dem zlib\ Ordner navigieren.
    - mit nmake -f win32\Makefile.msc kompilieren.
    - Boost herunter laden und die zlib.cpp aus libe\iostreams\source deinem Projekt hinzufügen (wahrscheinlich die einfachere Variante.

    Jetzt musst du in deinem VS Projekt dem Include Pfad den Pfad zu Boost hinzufügen.
    Außerdem musst du die zlib Bibliothek für den Linker hinzufügen, sowie den Pfad zu der Bibliothek.

    Nun solltest du mit Boost arbeiten können und damit entpacken können.

    Hier mal das Anwendungsbeispiel von der Boost Homepage:

    #include <fstream>
    #include <iostream>
    #include <boost/iostreams/filtering_streambuf.hpp>
    #include <boost/iostreams/copy.hpp>
    #include <boost/iostreams/filter/zlib.hpp>
    
    int main() 
    {
        using namespace std;
    
        ifstream file("hello.z", ios_base::in | ios_base::binary);
        filtering_streambuf<input> in;
        in.push(zlib_decompressor());
        in.push(file);
        boost::iostreams::copy(in, cout);
    }
    

    Mit dem .net Framework habe ich noch nicht gearbeitet, da kann ich dir wenig zu sagen.

    Ob Java einfacher zu lernen ist, ist schwer zu sagen. Je nachdem wen du fragst, wirst du eine andere Antwort bekommen.
    Java hat von hause aus, mehr "Bibliotheken" auf die du direkt zugreifen kannst ohne die zusätzlich zu installieren. Daher kommst du als Anfänger vlt schneller zum Ziel. Aber insgesamt glaube ich nicht, dass Java "einfacher" ist.



  • Hey,
    danke für die Rückmeldung und dem Code.

    Leider kam ich überhaupt nicht mehr damit zurecht und habe mich jetzt an Java "getratut".

    Das fällt mir deutlich einfacher und ich bin eigentlich schon echt weit.
    Jetzt stehe ich aktuell vor dem Problem die Dateien auf Datum und Zeit miteinander zu vergleichen und die zeitlich aktuellere Datei mit der zeitlich älteren Datei zu ersetzen.

    Hier der Link zum neuen Thema


Log in to reply