2016-07-27 91 views
0

我想在TIdHtttp上使用PUT上傳文件。我發現Remy Lebeau的回答是不使用PUT,而是使用POST。使用PUT上傳TIdHTTP文件

但在我的情況下,我無法做到這一點,因爲我使用第三個API,它指定我需要使用PUT。如果我嘗試使用POST,它會返回一條消息,指出方法不被允許。

基本上,我試圖做這樣的事情:

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); 

但是,當我這樣做,我得到一個500 - Internal server error

如果我刪除了:

FHttpComunication.Request.ContentType := 'multipart/form-data'; 

我得到400 - Bad Request

我已經嘗試直接從瀏覽器(高級REST客戶端 - 鉻)做出請求,它的工作原理。所以API正在工作。當它工作郵件的標題是:

 
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 

的代碼是不是在這裏,但我是配置的授權信息,它的工作,我可以檢查這一點,因爲我可以用別人調用API。

更新

這是我想要使用PUT的API:http://docs.transifex.com/api/translations/#put

方式,我試圖:

1)這一個返回500 - Internal Server Error。我嘗試過創建內容類型爲application/octet-stream的DS對象。但我得到了同樣的錯誤。

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)答案中提示的方式,但它不工作。我也收到了錯誤500

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; 
+0

提供包含您設置的所有標題的完整代碼。 「AddFile」過程中的最後一個參數應該是「application/octet-stream」。如果不使用'TIdMultiPartFormDataStream',請勿手動設置'ContentType'。否則使用'RequestContentType'函數,正如我所提到的。從'TIdHTTP.Request.RawHeaders保存你的頭文件。文字「或使用」OnIdHTTPHeadersAvailable「事件並比較您的標題。如果您發送完全相同的請求,它必須工作。 – smooty86

回答

4

該API由設計破壞。您不應該混合使用multipart/form-dataPUT。你應該把它像這樣

FPutData:=TFileStream.Create('yourfile.dat', fmOpenRead or fmShareDenyWrite); 
FHTTP.Put('http://...', FPutData, FResponseStream); 

但是,如果它不工作,問題可能是你沒有設置正確ContentType,它不包括邊界。修復它這樣

FHTTP.Request.ContentType:=DS.RequestContentType; 

哪裏DS是你TIdMultiPartFormDataStream

+2

'TIdMultipartFormDataStream'旨在與Post()'一起使用,並且該版本的Post()'在內部設置ContentType,並帶有邊界。如果你Put()'TIdMultipartFormDataStream',那麼是的,你必須手動設置ContentType,並且應該使用'RequestContentType'。 –

+0

它不工作!我仍然收到錯誤的要求。我試過兩種情況。我奇怪有關問題的更多信息。 –

0

我發現了這個問題。這是關於我必須制定的邊界。所以最終結果是:

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; 
+1

真是一個驚喜!我昨天告訴過你使用'RequestContentType',並且你再次手動設置邊界... – smooty86

+0

oooo對不起!我沒有看到它。創建一個答案,我會接受它! –

+0

但在答案中提到... – smooty86