Datei aus einer URL öffnen



  • Aktuell habe ich ein Programm, welches Dateien, die sich auf einem Netzwerkpfad befinden, öffnet und daraus Informationen ausliest. Es erfolgt ausschließlich ein lesender Zugriff. Ein Abspeichern ist nicht notwendig. Jetzt wird das System derart umgestellt, dass die Dateien in eine Art Cloud transferiert werden. Für den Zugriff bekomme ich dann einen Link. Jetzt ist das Problem, dass der Zugriff auf die Dateien aktuell über CFile realisiert ist. CFile benötigt für lpszfilename
    eine Zeichenfolge, die den Pfad zur gewünschten Datei enthält. Der Pfad kann relativ, absolut oder ein Netzwerkname (UNC) sein. Wie kann man das jetzt technisch realisieren? Muss man die Datei immer erst vorher manuell in ein temporäres Verzeichnis Downloaden oder gibts die Möglichkeit, die Inhalte aus der URL zu streamen?



  • Du musst die datei herunterladen. Ob du den "download" in eine temporäre Datei umleitest oder direkt den content in einen memory buffer speicherst ist da egal



  • Vielen Dank. Hab ich mir schon fast gedacht. Dann wird wohl CInternetSession mein Freund werden.



  • ich hatte jetzt einen ersten Versuch mit URLDownloadToFile unternommen. Das klappt bei URLs mit http ganz gut. Https will der anscheinend nicht....



  • So, nächster Versuch:

    CInternetSession isession;
    CString url = _T("https://mydokuurl.com/Test.docx");
    CString filename = _T("C:\\test\\Test.docx");
    CHttpFile *httpfile = (CHttpFile*)isession.OpenURL(url, 1, INTERNET_FLAG_SECURE |
    	INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD);
    if (httpfile)
    {
    	// do something
    }
    

    Das funktioniert leider auch nicht. Er meint, dass das Zertifikat nicht gültig wäre. Geb ich das in einen x-beliebigen Browser ein lädt er die Datei herunter. Auch da sind keine weiteren Zertifikate installiert. Was wohl aber ist ist die Tatsache, dass das Serverzertifikat für https und SSL vom Server (also intern) erstellt wurde. Möglicherweise macht der Browser da was anders als ich es mit dem Quellcode vorhabe. Kann mir da jemand einen Tipp geben?





  • Vielen Dank. Habe das wie folgt geändert:

    CInternetSession isession;
    CString url = _T("https://mydokuurl.com/Test.docx");
    DWORD dwFlags =	INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
    		INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
    		INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
    		INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
    isession.SetOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags, 0);
    CString filename = _T("C:\\test\\Test.docx");
    CHttpFile *httpfile = (CHttpFile*)isession.OpenURL(url, 1, INTERNET_FLAG_SECURE |
    	INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD);
    if (httpfile)
    {
    	// do something
    }
    

    Das funktioniert aber leider auch nicht. Ich finde, dass auch die Doku dazu wenig aussagekräftig ist. Was mache ich hier falsch?



  • Ich habe das jetzt so gelöst und es funktioniert:

    CString url = _T("https://mydokuurl.com/Test.docx");
    CString filename = _T("C:\\test\\Test.docx");
    IStream* stream;
    if (S_OK != URLOpenBlockingStream(NULL, URL, &stream, 0, NULL))
    {
    	AfxMessageBox(_T("Error"));
    	return;
    }
    char buff[100];
    unsigned long bytesRead;
    
    try
    {
    	CFile file;
    	if (file.Open(filename, CFile::modeCreate | CFile::modeWrite))
    	{
    		while (true)
    		{
    			stream->Read(buff, 100, &bytesRead);
    			file.Write(buff, bytesRead);
    			if (0U == bytesRead)
    			{
    				break;
    			}
    		}
    		file.Close();
    	}
    }
    catch (CFileException *e)
    {
    	e->ReportError();
    	e->Delete();
    }
    stream->Release();
    


  • stream->Release() solltest du immer aufrufen, nicht bloß, wenn die Datei geöffnet werden kann und keine Exception ausgelöst wird.
    Noch besser (und einfacher) wäre es, wenn du dir eine RAII-Klasse für URLOpenBlockingStream und stream->Release erzeugst und diese dann verwendest (das bietet sich generell bei allen C-lastigen Resourcefunktionalitäten an - das macht die MFC ja auch so)!



  • @Th69 Vielen Dank für den Hinweis. Ist klar, wenn Open fehlschlägt wird das nicht aufgerufen. Hab das jetzt unten hin gepackt. Ich werde das in eine eigene Klasse packen, da ich das sicher öfters brauche. Dann erledigt die Klasse das Release.


Anmelden zum Antworten