![]() |
TIdHttpServer JPG-Upload von HTML
Hi,
ich möchte gerne in meinem TIdHTTPServer über ein HTML-Formular Bilder/Dateien hochladen, die dieser dann speichert. Um die Dateien aus dem Stream zu extrahieren habe ich mir (zugegeben im Inet geklaut, woher weiß ich nicht mehr) folgende Methode:
Delphi-Quellcode:
die grundsätzlich erst mal funktioniert.
procedure TfrmWSMain.ExtractFiles(var ARequestInfo: TIdHTTPRequestInfo;
Files: TStringList); var ms : TMemoryStream; newdecoder, Decoder: TIdMessageDecoder; boundary, startboundary : String; msgEnd : Boolean; tmp : String; I : Integer; fname : String; tsValues : TStringList; begin if Pos('krank', LowerCase(ARequestInfo.Document)) > 0 then begin if ARequestInfo.PostStream<>nil then begin ARequestInfo.PostStream.Position:=0; msgEnd:=False; boundary:=ExtractHeaderSubItem(ARequestInfo.ContentType, 'boundary', QuoteHTTP); startboundary := '--' + boundary; repeat tmp:=ReadLnFromStream(ARequestInfo.PostStream, -1, True); until tmp=startboundary; Decoder:=TIdMessageDecoderMIME.Create(nil); TIdMessageDecoderMIME(Decoder).MIMEBoundary:=boundary; tsValues:=TStringList.Create; try repeat Decoder.SourceStream:=ARequestInfo.PostStream; Decoder.FreeSourceStream:=False; Decoder.ReadHeader; Inc(i); case Decoder.PartType of mcptText, mcptAttachment: begin ms:=TMemoryStream.Create; ms.Position:=0; newdecoder:=Decoder.ReadBody(ms, msgEnd); tmp:=Decoder.Headers.Text; fname:=Decoder.Filename; if Decoder<>nil then TIdMessageDecoderMIME(Decoder).MIMEBoundary:=boundary; Sleep(100); if fname<>'' then begin ms.SaveToFile(fname); //msgEnd:=True; end else begin ms.SaveToFile(IntToStr(i)+'.txt'); end; ms.Free; end; mcptIgnore: begin try FreeAndNil(Decoder); Decoder:=TIdMessageDecoderMIME.Create(nil); TIdMessageDecoderMIME(Decoder).MIMEBoundary:=boundary; finally ms.Free; end; end; mcptEOF: begin FreeAndNil(Decoder); msgEnd:=True; end; end; until (Decoder = nil) or (msgEnd); finally if Decoder<>nil then Decoder.Free; end; end; end; end; HTML sieht so aus:
Code:
ich bekomme für jedes Input die Daten in eine Datei.
<tr><form data-ajax="false" id="krank" method="post" action="krank.php" enctype="multipart/form-data">
<td><label>Krank von</label></td> <td><input type="text" name="krankvon" id="krankvon" style="width:100%;" focus></td> </tr><tr> <td><label>Krank bis</label></td> <td><input type="text" name="krankbis" id="krankbis" style="width:100%;" focus></td> </tr><tr> <td><label>Bild 1</label></td> <td><input type="file" name="datei1" id="datei1" accept="text/*"></td> </tr><tr> <td><label>Bild 2</label></td> <td><input type="file" name="datei1" id="datei2" accept="text/*"></td> </tr><tr> <td><label>Bild 3</label></td> <td><input type="file" name="datei1" id="datei3" accept="text/*"></td> </tr><tr> <td colspan="2"> <input type="submit" value="Absenden" style="width:100%;"> </td> </tr></form> 2 Probleme habe ich noch, welches ich selbst nicht lösen kann: 1. Dateiname der Dateien wird nicht erkannt und 2. die hochgeladenen JPG's sind fehlerhaft. Die Dateigröße ist geringfügig größer. Soweit ich das mit einem Hexeditor erkannt habe, wird wohl aus einem LF ein CRLF. Damit verändert sich der Inhalt und das Bild wird nicht mehr korrekt dargestellt. Wer kann mir bei der Lösung helfen? |
AW: TIdHttpServer JPG-Upload von HTML
Wieso wählst du im HTML Teil das Schema text/*: accept="text/*, wenn du Bilder hochladen willst?
![]() ![]() |
AW: TIdHttpServer JPG-Upload von HTML
Zitat:
|
AW: TIdHttpServer JPG-Upload von HTML
Unter
![]() Kann es sein, dass die Indy-Version veraltet ist? |
AW: TIdHttpServer JPG-Upload von HTML
Danke für den Link.
Das würde gerne mal ausprobieren. Ich verwendet die in 10.3 Rio mitgelieferte Indy-Version. Wenn ich die im Link aufgeführten Änderungen an der IdMessageCoderMIME.pas ausprobieren will, muss ich diese ja neu compilieren. Ich muss zugeben, dass ich nicht weiß, wie ich das hinbekomme, das das keine von mir nachinstallierte Komponente ist. Anhand des Haltepunkts kann ich erkennen, dass er diese nicht automatisch neukompiliert, auch wenn ich mein Projekt bereinige. Wie geht das? |
AW: TIdHttpServer JPG-Upload von HTML
Okay, ich bin ein Schritt weiter. Ich habe mir einfach erst einmal die IdMessageCoderMIME.pas ins Projekt kopiert, dann wird diese verwendet. Dort habe ich dann den Fix angewendet. Jetzt werden meine Bilder korrekt und in richtiger Größe geschrieben.
Nun habe ich aber ein neues Problem: Nachdem alle Attachments gelesen wurden, erfolgt ein erneuter Durchlauf der Repeat-Schleife, da msgEnd nicht auf True gesetzt wurde, also der Case auf Decoder.PartType nicht mcptEOF liefert. So meine Vermutung. Er läuft dann in die Zeile
Delphi-Quellcode:
und kehrt nicht mehr zurück.
newdecoder:=Decoder.ReadBody(ms, msgEnd);
Müsste ReadBody nicht dann msgEnd auf True setzen? Bzw. Decoder.PartType nicht mcptEOF liefern? |
AW: TIdHttpServer JPG-Upload von HTML
Zitat:
![]() |
AW: TIdHttpServer JPG-Upload von HTML
Zitat:
Jetzt mit dem Fix werden die hochgeladenen Bilder auch korrekt aus dem Stream extrahiert. Nur erkennt ReadBody das Ende nicht wirklich, und kehrt nach dem letzten Attachment nicht mehr zurück. Wenn jemand dazu noch einen Tipp hätte..... |
AW: TIdHttpServer JPG-Upload von HTML
Einen ersten Workaround habe ich gefunden. In der Unit IdMessageCoder Methode TIdMessageDecoder.ReadHeader Zeile 307
Alt:
Delphi-Quellcode:
Geänder in:
if LStrmPos >= LStrmSize then begin
Result := ''; Exit; end;
Delphi-Quellcode:
Auszug aus der IdMessageCoderMIME, Methode TIdMessageDecoderMIME.ReadBody (Ein paar Zeilen unter dem FIX):
if LStrmPos >= LStrmSize then begin
Result := '.'; //<-- in der IdMessageCoderMIME wird auf . getestet und VMsgEnd gesetzt Exit; end;
Delphi-Quellcode:
So scheint es bei mir zu funktionieren. Jetzt muss ich nur noch ergründen, warum der Filename nicht ausgewertet wird. Erste Vermutung: Implementierung fehlt wohl noch. (FFilename wird in IdMessageCoder/IdMessageCoderMIME nie beschrieben).
if LLine = '.' then begin {Do not Localize}
VMsgEnd := True; Break; end; |
AW: TIdHttpServer JPG-Upload von HTML
'ne Mail endet mit 'ner Zeile, die nur einen Punkt enthält.
Von daher erscheint mir Deine Änderung korrekt und sinnvoll. Je nach Software folgt der Zeile mit dem Punkt auch noch 'ne Leerzeile weshalb die ursprüngliche Variante wohl (meist) funktioniert. Man kann sich leider nicht sicher darauf verlassen, dass die letzte Zeile einen Punkt enthält. Eventuell solltest Du in Deiner Variante prüfen, ob die letzte Zeile einen Punkt enthält oder eine Leerzeile ist. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz