2016-07-27 59 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