Delphi Indy Datei via URL downloaden und temporär öffnen?
Hallo zusammen,
ich lade momentan folgendermassen via Indy eine Datei herunter:
Code:
Das funktioniert soweit auch, dennoch habe ich hierzu zwei Fragen:
IdHTTP.Get(Host + '/restapi/index.php/document/' + String(lvSearch.Items.Item[i].Data) + '/content', Stream);
Stream.SaveToFile(GetSpecialFolder(CSIDL_APPDATA) + '\test.msg'); 1. Ich muss ja derzeit für das SaveToFile die Dateiendung und vorzugsweise auch den Dateinamen vorab wissen. Besteht die Möglichkeit, dass mir die Indy Komponente das vorab liefern kann so dass die Datei (Dateityp hinter dem Download kann sich ändern) immer mit korrekter Endung gespeichert wird? 2. Gibt es eine Möglichkeit, die heruntergeladene Datei nicht zu speichern und quasi "nur" temporär direkt aus dem Stream heraus zu öffnen? Falls nicht, besteht die Möglichkeit zu erkennen ob die heruntergeladene Datei noch offen ist und falls nicht, diese dann zu löschen? Zum Hintergrund: Ich bastel gerade an einem Outlook Addin, welches in einem DMS nach Dokumenten sucht. Durch Doppelklick auf das Dokument, soll dieses vom DMS via URL heruntergeladen und geöffnet werden. Aber lediglich nur zur Anzeige. Wenn ich das Dokument wieder schließe, dann soll die temporär heruntergeladene Datei gelöscht werden. Vielen Dank im Voraus schon mal für Eure Hilfe. Falls Ihr mehr Informationen benötigt, so meldet Euch gern. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Sowas?
Delphi-Quellcode:
Statt TStringList kannst Du auch alles andere nehmen, was über eine Methode LoadFromStream o. ä. verfügt. Das könnte z. B. ein TMemo sein. 'nen Dateinamen brauchst Du für sowas nicht.
var
sl : TStringList; sUrl : String; begin sl := TStringList.Create; sUrl := Format('%s/restapi/index.php/document/%s/content', [Host,String(lvSearch.Items.Item[i].Data)]); IdHTTP.Get(sUrl, Stream); Stream.Position := 0; sl.LoadFromStream(Stream); ShowMessage(sl.Text); sl.Free; end; Willst Du nur Infos über einen "demnächst" durchzuführenden Download, kannst Du auch eine Head-Abfrage machen. Aus RawHeaders ('ner TStringList) kannst Du Dir dann die gewünschte Info raussuchen. Dann wird aus Deiner Routine sowas in der Art:
Delphi-Quellcode:
Ungetestet hingedaddelt.
var
sl : TStringList; sUrl : String; sDatei : String; begin sl := TStringList.Create; sUrl := Format('%s/restapi/index.php/document/%s/content', [Host,String(lvSearch.Items.Item[i].Data)]); IdHTTP.Head(sUrl); // Wenn das Laden des Inhaltes nicht direkt per Stream möglich sein sollte: sDatei := Format('%s\%s',[GetSpecialFolder(CSIDL_APPDATA),IdHTTP.Response.RawHeaders.Values['Filename']]); // oder wie das da im konkreten Einzelfall heißen mag. IdHTTP.Get(sUrl, Stream); Stream.SaveToFile(sDatei); sl.LoadFromFile(sDatei); ShowMessage(sl.Text); sl.Free; DeleteFile(sDatei); end; |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Indy enthält eine Methode GetMIMEDefaultFileExt mit der sich zu einem MIME-Typ die Dateiendung ermitteln lässt:
Delphi-Quellcode:
Beispiel: GetExtension('application/pdf') -> Endung '.pdf'
uses
..., IdGlobalProtocols; function GetExtension(const AMIMEType: string); begin Result := GetMIMEDefaultFileExt(AMIMEType); end Quelle: https://stackoverflow.com/a/44954955/80901, mit Hinweise zur Optimierung. Den MIME-Typ sendet der HTTP Server mit der Antwort als Response Header mit, d.h. die Funktion arbeitet auch dann wenn der URL selbst keine Datei-Endung enthält. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Erstmal Danke für Eure Antworten.
Scheinbar gibt mir aber der Server keinen MIME Typ zurück. Kann man das irgendwie prüfen? |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Was steht denn in IdHTTP.Response.RawHeaders.Text?
Ist da nix auswertbares bei? Könntest Du den Inhalt davon eventuell mal hier posten? |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Nee da ist leider nix dabei:
Code:
Date: Fri, 07 Jun 2019 08:34:41 GMT
Server: Apache/2.4.29 (Ubuntu) Keep-Alive: timeout=5, max=99 Connection: Keep-Alive Content-Type: text/html; charset=UTF-8 Kann es evtl. an der Apache Konfiguration liegen? |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Zitat:
Was passiert denn wenn man mit dem Browser eine Datei im CMS auswählt / anklickt und diese herunterlädt, zeigt der Browser dann die richtige Dateierweiterung im Download-Dialog an, oder nur HTML? Wenn es im Browser anders ist als beim Indy-HTTP Download, dann kann es an einem fehlerhaft konfigurierten Request aus Indy liegen... |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Nimm doch Content-Type: text/html; charset=UTF-8.
Davon brauchst Du "text/html", das spendierst Du dann GetMIMEDefaultFileExt und die gesuchte Dateiendung sollte da rauskommen. Ungetestet sowas in der Art:
Delphi-Quellcode:
function GetExtension(const AMIMEType: string);
begin Result := GetMIMEDefaultFileExt(AMIMEType); end; ... var sType : String; i : Integer; begin sType := IdHTTP.Response.RawHeaders.Values['Content-Type']; i := Pos(' ',sType); if i > 0 then sType := Copy(sType,1,i - 1); ShowMessage(GetExtension(sType)); ... end; |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Zitat:
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Wir wissen aber nicht, ob Indy konstant text/hmtl erhält, sondern nur aus einem Beispiel, dass es bei diesem text/hmtl erhält.
Zuerst wäre also mal zu prüfen, ob Indy immer text/html enthält oder nur bei bestimmten Dokumenten. Und wenn man sich mal hier von der Delphipraxis die Headerdaten anschaut, so bekommt man auch keinen Mime-Type, sondern "nur" den Content-Type von 'nem Apache-Server geliefert. Und der passt immer zum Typ der geladenen Daten, wie z. B.:
Code:
Der Apache arbeitet schon durchaus korrekt.
text/html; charset=iso-8859-1
text/css application/javascript image/png image/gif ... Jedenfalls entnehme ich den Dateityp seit gefühlten Jahrzehnten regelmäßig dem Content-Type und das klappte bisher immer, egal welcher Webserver auf der "Gegenseite" steht. Der TE sollte also bitte erstmal prüfen, ob er immer nur text/html als Content-Type geliefert bekommt oder nur bei HTML. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hallo zusammen,
ich habe gerade mal nachgeschaut, ich bekomme immer text/html, egal welcher Dateityp dahinter steckt. In meinem Header den ich oben gespostet habe, hatte ich versucht eine PDF Datei herunterzuladen. Im Browser funktioniert alles einwandfrei, da kann ich eine Datei problemlos runterladen und sie wird auch mit korrektem Namen und Endung gespeichert. Alles schon sehr merkwürdig. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Um welche Dateitypen handelt es sich, kannst Du das einschränken auf z. B. nur HTML, PDF ... oder musst Du mit "kann alles sein, was es so gibt" rechnen?
Ist es eingeschränkt auf bestimmte Typen, kannst Du das selbst auswerten. Du hast nach dem Get per Indy ja 'nen Stream. Die ersten 4 Byte einer PDF sind immer "%PDF", das kann man einfach abfragen. HTML beginnt mit <html, xml mit <xml ... Es kommt also auf die "Menge der möglichen Dateitypen" an, ob es nicht einfacher ist das "eben mal" selbst zu prüfen. Der FireFox hat 'ne Webkonsole, in der kann man sich die Headerdaten übersichtlich anschauen, kannst Du den bei Dir auch verwenden? Notfalls halt die Url, die Du Indy beim Get übergibst, mal per Copy&Paste dem Browser spendieren und den mal die Headerdaten anzeigen lassen. Bei anderen Browsern müsstest Du mal schauen, ob sie 'ne ähnliche Option bieten. Ansonsten: https://elmar-eigner.de/_freetools/h...r-auslesen.php https://www.gaijin.at/de/tools/webserver-spy Schau bitte mal nach, welche Webseite den Mime-Type nicht in Content-Type liefert. Literatur zur Definiton dessen, was im Header wie zu stehen hat: https://www.w3.org/Protocols/rfc2616....html#sec14.17 |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Zitat:
Wenn es dann auch funkioniert, tippe ich stark auf ein Problem mit dem Indy Request. Das zu untersuchen ist aber auch möglich. Man muss dazu den HTTP Traffic des Browsers aufzeichnen. Über F12 (Entwicklermodus) kann man loggen, was im Detail an den CMS Server gesendet wird, und welcher MIME-Typ im Response Header zurückkommt. Hat man den funktionierenden Request, muss man diesen mit Indy nachbauen. Wie sieht der Indy Request im HTTP Header aus? Eventuell fällt dort etwas auf. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Was auch noch sein könnte, dass im Browser zuerst 'ne HTML-Seite angefordert wird und dann per HTTP-Code 302 (o. ä.) eine Weiterleitung zur PDF erfolgt, die dann mit 'nem passenden Content-Type geliefert wird.
Wie ist die Indykomponete konfiguriert? Folgt sie Redirects? Wenn nein, das mal bitte ändern. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hallo zusammen,
danke für Eure Denkanstöße. Problem gelöst. Es lag an einer fehlerhaften Apache Konfiguration. Eine Frage habe ich noch offen. Wenn ich jetzt mittels Indy Response Stream eine Datei herunterlade, kann ich diese irgendwie "nur" temporär herunterlacen, also nur solange auf der Platte belassen so lange sie geöffnet ist? Evtl. beim Download und Speichern der Datei ein Windows-Flag "zu löschen" oder ähnliches zu setzen? |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hallo,
Zitat:
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Das geht aber nur in einem Loop solange meine Applikation läuft.
Ich würde gern die Datei zum Löschen markieren so dass - sie sobald sie nicht mehr geöffnet ist - gelöscht wird. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Wie wäre es mit CreateFile und dem Flat FILE_FLAG_DELETE_ON_CLOSE?
Zitat:
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hallo Michael,
das klingt an sich nicht schlecht aber... ich erstelle momentan die Datei aus einem Stream:
Code:
CreateFile jedoch erstellt die Datei ja auch und ich kann da ja nur einen Dateinamen übergeben, jedoch keinen Stream oder habe ich was übersehen?
procedure TfrmSearch.lvSearchDblClick(Sender: TObject);
begin Stream := TMemoryStream.Create; try IdHTTP.HandleRedirects := True; IdHTTP.Get(Host + '/restapi/index.php/document/' + String(lvSearch.Items.Item[i].Data) + '/content', Stream); Stream.SaveToFile(GetSpecialFolder(CSIDL_APPDATA) + '\' + ResponseFileName); except on E:Exception do begin ShowMessage('Fehler: ' + E.Message); end; end; Stream.Free; end; |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Du bekommst ein Dateihandle zurück. Eventuell kannst du den an den Stream übergeben.
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Zitat:
https://stackoverflow.com/questions/...-on-close-flag Es kommt dann vermutlich die Fehlermeldung: "The process cannot access the file because it is being used by another process." |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hallo zusammen,
ich lade die Datei momentan so herunter in einen MemoryStream:
Delphi-Quellcode:
Stream := TMemoryStream.Create;
IdHTTP.HandleRedirects := True; IdHTTP.Get('http://192.168.178.244/restapi/index.php/document/4/content', Stream); Memo1.Text := IdHTTP.Response.RawHeaders.Text; ResponseFileNameTemp := StringReplace(IdHTTP.Response.RawHeaders.Values['Content-Disposition'], 'attachment; filename="', '', [rfReplaceAll]); ResponseFileName := StringReplace(ResponseFileNameTemp, '"', '', [rfReplaceAll]); Stream.SaveToStream(CreateUnbuffedFilestream(GetSpecialFolder(CSIDL_APPDATA) + '\' + ResponseFileName)); Die Funktion "CreateUnbufferedFilestream" sieht so aus:
Delphi-Quellcode:
function CreateUnbuffedFilestream(const filename:string):TStream;
var FileHandle, hnd : THandle; begin FileHandle := CreateFile(PChar(filename), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, 0); if hnd <> INVALID_HANDLE_VALUE then begin result := THandleStream.Create(FileHandle); ShellExecute(Application.Handle, 'open', PChar(filename), nil, nil, sw_show); end else result := nil; end; Das funktioniert soweit jedoch kann die Dtaei mittels ShellExecute nicht geöffnet werden. Bekomme da immer die Meldung dass die Datei in Benutzung ist. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Zitat:
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hmm schade, in meinem Beispiel war das jetzt der Adobe Reader.
Gibt es denn eine andere Möglichkeit??? |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Zitat:
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Delphi-Quellcode:
Eine Datei zu einer internen Liste hinzufügen, die dann beim Schließen der Anwendung automatisch gelöscht werden. Allerdings geht das nur, wenn die Datei nicht auch noch in einer externen Anwendung geöffnet ist.
TemporaryFilesManager.Add(aFilenameWithFullPath);
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hallo Peter,
danke, das funktioniert perfekt. Schön wäre jetzt noch eine Möglichkeit, die temporäre(n) Datei(en) zu löschen die nicht gelöscht werden konnten, weil die Applikation noch offen war, aber das könnte man ja mit einem geplanten Task evtl. lösen. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Zitat:
Was Du relativ leicht machen kannst ist folgendes: lege die temporären Dateien in einem Unterordner des temp-Verzeichnisses ab. Den kannst Du dann einfach bei jedem Programmstart leerputzen, damit bleiben die nicht gelöschten Dateien nur bis zur nächsten Session liegen. |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Klasse Tip, genau so mache ich das mal. Danke Dir!
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hmm..
Alternative: MoveFileEx(PChar(YourFileToDelete), nil, MOVEFILE_DELAY_UNTIL_REBOOT) Erzeuge deine Dateien ganz normal und rufe dann direkt hierfür die obrige MoveFileEx funktion auf. Nun dein ShellExecute und die Datei kann geöffnet/Angezeigt werden. Beim nächsten Reboot von Windows werden diese Dateien gelöscht. Ist nicht schön, dass dies erst beim Reboot erfolgt, aber immerhin.. ;) |
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Prinzipiell gute Idee, aber aus der Doku:
Code:
This value can be used only if the process is in the context of a user who belongs to the administrator group or the LocalSystem account.
|
AW: Delphi Indy Datei via URL downloaden und temporär öffnen?
Hmm..
OK, sorry, die kleine Zeile ist mir in der API-Beschreibung von MS unter gegangen.. ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz