Lebenslauf HTTP-Post - /upload mit Indy
Ich versuche, die Wiederaufnahme einer upload mit indy (HTTP Post), der code sieht so aus (mit Delphi 2010, Indy 10.4736):
IdHttp.Head('http://localhost/_tests/resume/large-file.bin');
ByteRange := IdHttp.Response.ContentLength + 1;
// Attach the file to post/upload
Stream := TIdMultipartFormDataStream.Create;
with Stream.AddFile('upload_file', 'D:\large-file.bin', 'application/octet-stream') do
begin
HeaderCharset := 'utf-8';
HeaderEncoding := '8';
end; // with
with IdHTTP do
begin
IOHandler.LargeStream := True;
with Request do
begin
ContentRangeStart := ByteRange;
ContentRangeEnd := (Stream.Size - ByteRange);
ContentLength := ContentRangeEnd;
ContentRangeInstanceLength := ContentLength;
end; // with
Post('http://localhost/_tests/resume/t1.php', Stream);
end; // with
aber laden fortsetzen funktioniert nicht 🙁
Schaute ich in Indy ' s code, es scheint, dass diese Funktion in IdIOHandler.pas
TIdIOHandler.Write()
immer mit kompletten streams/Dateien (da der parameter ASize: TIdStreamSize scheint immer 0, die nach dem Strafgesetz bedeutet, dass das senden der vollständigen Datei/stream).
Dies verhindert, dass indy von der Wiederaufnahme der upload.
Meine Frage ist: ist es möglich zu verhindern, dass die vollständige Datei?
Einstellung content Bereich nichts verändert. Ich habe auch gezwickt indy-code (modifiziert 3 Linien), um indy zu gehorchen, um den Inhalt Palette /stream position, aber es ist buggy und indy immer am Ende hängen in IdStackWindows.pas, weil ein unendliches timeout hier:
TIdSocketListWindows.FDSelect()
- Sollten Sie verwenden
PUT
für, die. - Hier ist, was remy lebeau sagte über put
- Keine Ahnung, vermutlich hat er Gespräche über PHP4. Aber ja, deine Wünsche sind nicht kompatibel mit der POST.
- Die Wiederaufnahme der Dateien ist nicht kompatibel mit
PUT
. Ich sagte so viel,POST
, auf der anderen Seite, ist nur beliebige Daten. Das empfangende Skript entscheidet, was zu tun mit den Daten, also es könnte theoretisch verwendet werden, für die Wiederaufnahme. In der Praxis selten ist.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Als ich Ihnen sagte, in Ihre frühere Frage, Sie zu posten haben eine
TStream
mit dem Rest der Datei Daten hochladen. Verwenden Sie nichtTIdMultipartFormDataStream.AddFile()
, wie Sie die gesamte Datei. Verwenden Sie dieTStream
überladene version vonTIdMultipartFormDataStream.AddFormField()
statt.Sowie
TIdHTTP
ist nicht entworfen, um die Achtung derContentRange...
Eigenschaften. Die meisten derRequest
Eigenschaften werden lediglich die entsprechenden HTTP-Header nur, Sie haben keinen Einfluss auf die Daten. Das ist, warum Sie Ihre Bearbeitungen brach es.Versuchen Sie dies:
Mit dieser sagte, ist dies ein GROBER MISSBRAUCH von HTTP-und
multipart/form-data
. Für den Anfang, dieContentRange
Werte sind in der falschen Stelle. Sie diese anwenden, um die gesamteRequest
als ganzes, was falsch ist. Sie müssten angewandt werden, um dieFormField
statt, aberTIdMultipartFormDataStream
derzeit nicht unterstützen. Zweitensmultipart/form-data
wurde nicht entwickelt, um verwendet werden, wie dies ohnehin. Es ist in Ordnung für das hochladen einer Datei von Anfang an, aber nicht für die Wiederaufnahme einer gebrochenen hochladen. Sie sollten wirklich aufhören, mitTIdMultipartFormDataStream
und übergeben Sie einfach die Datei, die Daten direkt zuTIdHTTP.Post()
wie ich früher vorgeschlagen, zB:.
Ich schon bereits zuvor erläutert, wie Sie auf die raw -
POST
Daten in PHP.TIdMultipartFormDataStream
im Vergleich zu einem einfachenTStream
ist weit übertrieben für das, was Sie versuchen zu tun. Die Buchung einer einfachenTStream
behandelt große Dateien genauso gut, wenn nicht besser als, die Entsendung einerTIdMultipartFormDataStream
ohne Umgang mit all den zusätzlichen overhead. Und wie ich bereits zuvor erläutert, HTTP bietet keine native Unterstützung für das hochladen fortsetzen, so dass jede Lösung, die Sie verwenden, wird ein hack da, die Sie schreiben müssen die backend-PHP-Skript, um es zu unterstützen, manuell sowieso.TIdMultipartFormDataStream
Kräfte der input-stream istPosition
zurück auf 0, das ist also nicht hilfreich. Es gibt Drittanbieter-TStream
- Implementierungen zur Verfügung (oder eigene schreiben, wie basierend aufTIdEventStream
) umschließt, die eine EingabeTStream
zu entlarven eine Teilmenge der Daten. Sie können versuchen, mit, dass, wie der Eingang zuAddFormField()
. Ansonsten einfach STOPP mitmultipart/form-data
Beiträge für Ihre uploads. Es ist NICHT ENTWORFEN für das, was Sie verwenden es für.TFileStream
vonSize=50
und Sie wollte zu überspringen, die ersten 10 bytes. Sie realisieren die wrapper TStream istSeek()
zu versuchen nie, die QuelleTFileStream
vorPosition=10
, und auf einen Wert zurück, der offset von 10. In anderen Worten, ich Suche den wrapper TStream zuPosition=0
würde versuchen, die QuelleTFileStream
zuPosition=10
. Wenn der wrapper istSize
abgefragt wird, würde es wieder 40, nicht 50. So, Indy würden nur 40 bytes, die Schritte 10 bytes in die Datei.TStream
Umsetzung, die genau das tut -TIdHTTPRangeStream
im IdCustomHTTPServer.pas. Es ist ausgelegt für den Versand teilweise Blöcke von Daten von einer QuelleTStream
. Zugegeben, es ist HTTP-orientierten, aber, aber Sie können entfernen Sie die HTTP-handling.TIdHTTPRangeStream
ich würde einfach vorschlagen mit es wie es ist, das wäre viel einfacher:FStream := TFileStream.Create(...); RStream := TIdHTTPRangeStream.Create(FStream, StartPos, -1, True); If RStream.ResponseCode = 206 then begin MStream := TIdMultipartFormDataStream.Create; MStream.AddFormField(..., RStream, ...); IdHTTP.Post(..., MStream); MStream.Free; end; RStream.Free;
Content-Type
header ist komplett Durcheinander, was bedeutet, dass IhreAddFormField()
Parameter sind falsch. Übergeben Sie den Dateinamen (das sollte nur eine mit dem Namen von sich selbst, nicht einen vollständigen Pfad) in dem der content-Typ zu erwarten ist, und übergeben den Inhalt geben, wo das charset zu erwarten ist.AddFormField()
AufrufMultipartStream.AddFormField('upload_file', 'application/octet-stream', 'utf-8', RangeStream, ExtractFileName(FileName));
. Nun ist die hochgeladene Datei sieht so ausphp://input
mitmultipart/form-data
Beiträge, es sei denn, Sie bereit sind, zu analysieren, den raw MIME-Daten yoourself manuell. Ich sagte zu wechselnphp://input
NUR, WENN Sie damit aufhörenTIdMultipartFormDataStream
und nurPOST
die Quell-Datei direkt, zB:IdHTTP.Post('http://localhost/_tests/resume/t1.php', RangeStream)
. Wenn Sie zu halten mitmultipart/form-data
Beiträge, dann müssen Sie$_FILES
im PHP-code, um den Zugriff auf die Datei geschrieben Daten (pass$_FILES['upload_file']['tmp_name']
fopen() anstelle vonphp://input
).$_FILES['upload_file']['tmp_name'] to fopen() instead of php://input
da (basierend auf meinen tests) diese Methode nicht unterstützt resume (ie. entweder die Datei ist in voller Höhe gebucht oder nicht). also bin ich wieder zuphp://input
ich denke?$_FILES['upload_name']['tmp_nme
]` zufopen()
. Es ist eine neue temp-Datei erstellt, nur für diesen einzigen Stück gebuchten Daten. Öffnen Sie die Datei, fügen Sie Ihre Inhalte auf Ihre eigentliche Ziel-Datei, schließen und löschen der temp-Datei.