问题
I'd like to upload a file using PUT on TIdHtttp. I found an answer from Remy Lebeau saying to not use PUT, but use POST instead.
But, in my case I can't do it because I'm using a third API, and it specifies that I need to use PUT. If I try to use POST, it returns me a message saying that the Method is not allowed.
Basically, I'm trying to do something like this:
Response := TStringStream.Create;
DS := TIdMultiPartFormDataStream.Create;
DS.AddFile('fileUpload2', 'C:\Users\r.rezino\Desktop\teste.po', 'application/octet-stream');
FHttpComunication.Request.ContentType := 'multipart/form-data';
FHttpComunication.Put(UrlCmd, DS, Response);
But when I do it, I get a 500 - Internal server error
.
If I remove the:
FHttpComunication.Request.ContentType := 'multipart/form-data';
I get 400 - Bad Request
.
I already tried to do the request directly from browser (Advanced REST client - chrome) and it works. So the API is working. The header of the message when it works is:
PUT /api/2/project/XXXXXXXX/resource/export1po/translation/en/ HTTP/1.1 HOST: www.XXXXXXXXXXXXX.com authorization: Basic XXXXXXXXXXXXX content-type: multipart/form-data; boundary=----WebKitFormBoundaryPWT8bUdkQ1ZVLHdL accept: application/json accept-encoding: gzip, deflate accept-language: en-US,en;q=0.8 user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36 content-length: 1936 ------WebKitFormBoundaryPWT8bUdkQ1ZVLHdL Content-Disposition: form-data; name="fileUpload2"; filename="teste.po" Content-Type: application/octet-stream
The code is not here, but yes I configured the authorization information, it's working, I can check this because I can use others call to API.
Update
This is the API that I'm trying to use PUT
: http://docs.transifex.com/api/translations/#put
Ways that I tried:
1) This one return 500 - Internal Server Error
. I tried it creating the DS object with content type application/octet-stream
too. But I got the same error.
Response := TStringStream.Create;
DS := TIdMultiPartFormDataStream.Create;
DS.AddFile('fileUpload2', 'C:\Users\r.rezino\Desktop\teste.po', 'multipart/form-data');
try
FHttpComunication.Request.ContentType := 'multipart/form-data';
FHttpComunication.Put(UrlCmd, DS, Response);
Result := Response.DataString;
finally
Response.Free;
DS.Free;
end;
2) The way that was suggested on answers, but It's not working. I got the error 500
too.
PutData := TFileStream.Create('C:\Users\r.rezino\Desktop\teste.po', fmOpenRead or fmShareDenyWrite);
Response := TStringStream.Create;
try
FHttpComunication.Request.ContentType := 'multipart/form-data'; //I tried with and without it
FHttpComunication.Put(UrlCmd, PutData, Response);
Result := Response.DataString;
finally
Response.Free;
PutData.Free;
end;
回答1:
That API is broken by design. You should not mix multipart/form-data
and PUT
. You should send it like this
FPutData:=TFileStream.Create('yourfile.dat', fmOpenRead or fmShareDenyWrite);
FHTTP.Put('http://...', FPutData, FResponseStream);
But if it does not work, the problem is probably that you don't set a correct ContentType
, it does not include boundary. Fix it like this
FHTTP.Request.ContentType:=DS.RequestContentType;
Where DS
is your TIdMultiPartFormDataStream
.
回答2:
I found the problem. It was about the boundary that I must to set. So the final result is:
DS := TIdMultiPartFormDataStream.Create;
DS.AddFile('fileUpload2', 'C:\Users\r.rezino\Desktop\teste.po', 'application/octet-stream');
try
FHttpComunication.Request.ContentType := 'multipart/form-data; boundary=' + DS.Boundary;
FHttpComunication.Request.AcceptEncoding := '';
FHttpComunication.Request.Accept := '';
FHttpComunication.Request.Host := '';
FHttpComunication.Request.UserAgent := '';
FHttpComunication.Put(UrlCmd, DS, Response);
finally
DS.Free;
Response.Free;
end;
来源:https://stackoverflow.com/questions/38610279/use-put-to-upload-file-with-tidhttp