【问题标题】:Use PUT to upload file with TIdHTTP使用 PUT 通过 TIdHTTP 上传文件
【发布时间】:2016-12-01 07:20:31
【问题描述】:

我想在 TIdHtttp 上使用 PUT 上传文件。我从 Remy Lebeau 那里找到了一个答案,说不要使用 PUT,而是使用 POST。

但是,就我而言,我不能这样做,因为我正在使用第三个 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 客户端 - chrome)发出请求并且它可以工作。所以API正在工作。消息的标题是:

PUT /api/2/project/XXXXXXXX/resource/export1po/translation/en/HTTP/1.1 主机:www.XXXXXXXXXXXXX.com 授权:基本XXXXXXXXXXXX 内容类型:多部分/表单数据;边界=----WebKitFormBoundaryPWT8bUdkQ1ZVLHdL 接受:应用程序/json 接受编码:gzip,放气 接受语言:en-US,en;q=0.8 用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36 内容长度:1936 ------WebKitFormBoundaryPWT8bUdkQ1ZVLHdL 内容处置:表单数据;名称=“文件上传2”;文件名=“teste.po” 内容类型:应用程序/八位字节流

代码不在这里,但是是的,我配置了授权信息,它正在工作,我可以检查一下,因为我可以使用其他人调用 API。

更新

这是我正在尝试使用的 API PUT: 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;

【问题讨论】:

  • 提供您设置的所有标头的完整代码。 AddFile 过程中的最后一个参数应该是application/octet-stream。如果您不使用TIdMultiPartFormDataStream,请不要手动设置ContentType。否则使用我提到的RequestContentType 函数。从TIdHTTP.Request.RawHeaders.Text 保存您的标题或使用OnIdHTTPHeadersAvailable 事件并比较您的标题。如果您发送完全相同的请求,它必须工作。

标签: delphi indy transifex


【解决方案1】:

该 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

【讨论】:

  • TIdMultipartFormDataStream 旨在与Post() 一起使用,而该版本的Post() 在内部设置ContentType,并带有边界。如果你Put()TIdMultipartFormDataStream,那么是的,你必须手动设置ContentType,并且应该使用RequestContentType
  • 它不工作!我仍然收到错误的请求。我尝试了两种情况。我对问题的更多信息感到奇怪。
【解决方案2】:

我发现了问题。这是关于我必须设定的界限。所以最终的结果是:

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;

【讨论】:

  • 真是一个惊喜!我昨天告诉你使用RequestContentType,你又手动设置边界......
  • 太抱歉了!我没看到。创建一个答案,我会接受它!
猜你喜欢
  • 2012-03-03
  • 2016-02-22
  • 2019-05-09
  • 2010-10-18
  • 2019-07-27
  • 2022-08-09
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
相关资源
最近更新 更多