Indy 10分段上传到OneDrive错误

奥列格·阿迪别科夫(Oleg Adibekov)

我正在尝试使用POST分段上传到OneDrive,并获得“ HTTP / 1.1 400错误的请求”。IdLogFile:

Stat已连接。
发送10.02.2017 12:50:08:POST /v1.0/drive/root::/children HTTP / 1.0` <EOL>`Content-Type:multipart / related; boundary =“ Boundary”`<EOL>`内容长度:254` <EOL>`授权:Bearer EwA ...%3d` <EOL>`主机:api.onedrive.com` <EOL>`接受:text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8` <EOL>`Accept-Encoding:identity` <EOL>`User-Agent:Mozilla / 3.0(compatible; Indy Library <EOL> <EOL>`
发送10.02.2017 12:50:08:--Boundary` <EOL>`Content-ID:<metadata>`<EOL>`Content-Type:application / json` <EOL> `{“ name”:“ Dest.txt”,“ file”:{},“ @ content.sourceUrl”:“ cid:content”}`<EOL>`-边界`<EOL>`Content-ID:<内容> <EOL>内容类型:
Recv 10.02.2017 12:50:08:TTP / 1.1 400 Bad Request` <EOL>`Via:1.1 DM5SCH102210409(wls-colorado)`<EOL>`Content-Length:60` <EOL>`Content-Type:application / json` <EOL>`服务器:Microsoft-IIS / 8.5` <EOL>`P3P:CP =“ BUS CUR CONo FIN IVDo ONL OUR PHY SAMO TELo”`<EOL>`X-WLSPROXY:DM5SCH102210409` <EOL>` X-MSNSERVER:DM5SCH102231823` <EOL>`严格传输安全性:max-age = 31536000; includeSubDomains` <EOL>`X-QosStats:{“ ApiId”:0,“ ResultType”:2,“ SourcePropertyId”:0,“ TargetPropertyId”:42}`<EOL>`X-ThrowSite:1479.b891` <EOL >`X-AsmVersion:未知;16.0.0.0` <EOL>`X-MSEdge-Ref:Ref A:A9918FA26FAF469EB3797E9DAEA3172E Ref B:FRAEDGE0409 Ref C:2017年2月10日星期五01:50:09 PST` <EOL>`日期:2017年2月10日星期五09:50 :09 GMT` <EOL>`连接:

编码:

procedure TSaveFilter.UploadTest;
const
  URL = 'https://api.onedrive.com/v1.0/drive/root::/children';
  Boundary = 'Boundary';
var
  IdHTTP: TIdHTTP;
  MemoryStream: TMemoryStream;
  FileStream: TFileStream;

  procedure WriteLnString(str: AnsiString; CRLF: Boolean = True);
  begin
    if CRLF then str := str + #13#10;
    MemoryStream.Write(str[1], Length(str));
  end;
begin
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdHTTP.HandleRedirects := True;
    IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    IdHTTP.Request.BasicAuthentication := False;
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + FAccessToken;
    IdHTTP.Request.ContentType := Format('multipart/related; boundary="%s"', [Boundary]);

    MemoryStream := TMemoryStream.Create;
    try
      WriteLnString('--' + Boundary);
      WriteLnString('Content-ID: <metadata>');
      WriteLnString('Content-Type: application/json');
      WriteLnString('{"name":"Dest.txt", "file":{}, "@content.sourceUrl":"cid:content"}');
      WriteLnString('--' + Boundary);
      WriteLnString('Content-ID: <content>');
      WriteLnString('Content-Type: application/octet-stream', False);
      FileStream := TFileStream.Create('Source.txt', fmOpenRead);
      try
        MemoryStream.CopyFrom(FileStream, FileStream.Size);
      finally
        FileStream.Free;
      end;
      WriteLnString('--' + Boundary + '--', False);
      IdHTTP.Post(URL, MemoryStream);
    finally
      MemoryStream.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;

我究竟做错了什么?

这是一个工作请求(列出孩子):

Stat已连接。
发送10.02.2017 20:52:42:GET /v1.0/drive/root::/children?select=name,folder,file HTTP / 1.1` <EOL>`授权:Bearer EwA ...%3d` < EOL>`主机:api.onedrive.com` <EOL>`接受:text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8` <EOL>`Accept-Encoding :标识<EOL>用户代理:Mozilla / 3.0(兼容; Indy库)<EOL>``<EOL>” 
Recv 10.02.2017 20:52:43:H
Recv 10.02.2017 20:52:43:TTP / 1.1 200 OK` <EOL>`通过:1.1 BN2BAP4ED8CB55D(wls-colorado)`<EOL>`Content-Length:213` <EOL>`Content-Type:application / json; odata.metadata =最小`<EOL>`服务器:Microsoft-IIS / 8.5` <EOL>`P3P:CP =“ BUS CUR CONo FIN IVDoL OUR PHY PHY SAMO TELo” <EOL>`X-WLSPROXY:BN2BAP4ED8CB55D`` X-MSNSERVER:DM5SCH102231619` <EOL>`严格传输安全性:max-age = 31536000; includeSubDomains <EOL> OData版本:4.0` <EOL> X-AsmVersion:未知;16.0.0.0` <EOL>`X-MSEdge-Ref:Ref A:ECB06A4BE05B478AB36611C892C36CC7 Ref B:AM1EDGE0419 Ref C:Fri Feb 10 09:52:43 2017 PST``Date:Fri,10 Feb 2017 17:52:43 GMT `<EOL>``<EOL>`{“ @ odata.context”:“ https://api.onedrive.com/v1.0/$metadata#drives('me')/items('root')/子项(名称,文件夹,文件)”,
Stat已断开连接。
雷米·勒博(Remy Lebeau)

您的MIME数据格式错误,这就是服务器拒绝它的原因。

这是您发送的请求:

POST /v1.0/drive/root::/children HTTP / 1.0 
Content-Type:multipart / related; boundary =“边界”
内容长度:254
授权:Bearer EwA ...%3d
主机:api.onedrive.com
接受:text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8 
Accept-Encoding:身份
User-Agent:Mozilla / 3.0(兼容; Indy库)-- 

Boundary 
Content-ID:<metadata> 
Content-Type:application / json 
{“ name”:“ Dest.txt”,“文件”:{},“ @ content.sourceUrl”:“ cid:content”}-
边界
内容ID:<content>
内容类型:application / octet-stream <SourceContent> -Boundary--

如您所见,MIME数据都被弄乱了。具体来说,每个MIME字段都缺少一些必需CRLF的。就像HTTP标头和正文一样,MIME标头和正文由<CRLF><CRLF>序列分隔,并且CRLFTFileStream数据和紧跟其后的MIME边界之间必须有一个

该请求需要看起来像这样:

POST /v1.0/drive/root::/children HTTP / 1.0 
Content-Type:multipart / related; boundary =“ Boundary”
内容长度:260
授权:Bearer EwA ...%3d
主机:api.onedrive.com
接受:text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8 
Accept-Encoding:身份
User-Agent:Mozilla / 3.0(兼容; Indy库)-- 

Boundary 
Content-ID:<metadata> 
Content-Type:application / json 

{“ name”:“ Dest.txt”,“ file“:{},” @ content.sourceUrl“:” cid:content“}-
边界
内容ID:<content>
内容类型:application / octet-stream 

<SourceContent> 
--Boundary--

尝试使用以下代码填充TMemoryStream

MemoryStream := TMemoryStream.Create;
try
  WriteLnString('--' + Boundary);
  WriteLnString('Content-ID: <metadata>');
  WriteLnString('Content-Type: application/json');
  WriteLnString(''); // <-- ADD THIS!!!
  WriteLnString('{"name":"Dest.txt", "file":{}, "@content.sourceUrl":"cid:content"}');
  WriteLnString('--' + Boundary);
  WriteLnString('Content-ID: <content>');
  WriteLnString('Content-Type: application/octet-stream'); // <-- REMOVE THE FALSE!!!
  WriteLnString(''); // <-- ADD THIS!!!

  FileStream := TFileStream.Create('Source.txt', fmOpenRead);
  try
    MemoryStream.CopyFrom(FileStream, 0);
  finally
    FileStream.Free;
  end;

  WriteLnString(''); // <!-- ADD THIS!!!
  WriteLnString('--' + Boundary + '--', False);
  ...
finally
  MemoryStream.Free;
end;

话虽这么说,Indy有一个TIdMultipartFormDataStream通常TIdHTTP在发送multipart/form-data帖子使用OneDrive不支持multipart/form-data,但奇怪的是,OneDrive的文档明确指定了以下内容,该内容仅适用于multipart/form-data而不适用multipart/related

如果包含两个以上的部分,则该请求将被拒绝。每个部分都必须nameContent-Disposition标头中指定一个值,以指示它是哪个部分部件可以采用任何顺序,但应首先指定元数据部件。

但是,同一文档中给出的示例正在使用multipart/related,就像您的代码一样。Microsoft / OneDrive论坛和各种博客中都有关于是否使用multipart/form-datamultipart/related何时上传到OneDrive的讨论。一位OneDrive员工确实确认此问题需要最终解决。

以防万一OneDrive支持multipart/form-data,以下是使用示例TIdMultipartFormDataStream

procedure TSaveFilter.UploadTest;
const
  URL = 'https://api.onedrive.com/v1.0/drive/root::/children';
var
  IdHTTP: TIdHTTP;
  PostData: TIdMultipartFormDataStream;
begin
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdHTTP.HandleRedirects := True;
    IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    IdHTTP.Request.BasicAuthentication := False;
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + FAccessToken;

    PostData := TIdMultipartFormDataStream.Create;
    try
      PostData.AddFormField('metadata', '{"name":"Dest.txt", "file":{}}', 'utf-8', 'application/json');
      PostData.AddFile('content', 'Source.txt', 'application/octet-stream').FileName := '';
      IdHTTP.Post(URL, PostData);
    finally
      PostData.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Indy 10 HTTPS 代理

来自分类Dev

Indy10 GMTToLocalDateTime问题

来自分类Dev

Indy 10 SSL根证书

来自分类Dev

Delphi 7 Indy 10 ioHandler

来自分类Dev

Indy10 GMTToLocalDateTime问题

来自分类Dev

使用Indy将文件上传到FTP服务器

来自分类Dev

Delphi 2007和更新的Indy 10

来自分类Dev

Indy 10 TidTCPServer编码字符

来自分类Dev

Indy 10的IdSSLIOHandlerSocketOpenSSL使Delphi 5崩溃

来自分类Dev

Indy 10 IdTCPSever Readbytes加扰数据

来自分类Dev

Indy 10和sslvTLSv1_2

来自分类Dev

Delphi:从Indy9到Indy10的迁移:使用IdCustomHTTPServer和IdHTTPServer

来自分类Dev

Delphi / w Indy 10:错误400(idHTTP)之后获取内容

来自分类Dev

具有Indy FTP的SIGSEGV无法上传文件

来自分类Dev

Indy10,IdTCPClient的IOHandler发送其他数据

来自分类Dev

什么与Indy10中的GStack.HostToNetwork()对应

来自分类Dev

在Indy 10中是否可以使用IMAP GetLineResponse?

来自分类Dev

Indy 10-IdSMTP.Connect引发“无法加载SSL库”。

来自分类Dev

Indy 10无法安装到Delphi 5中

来自分类Dev

如何重建Delphi XE2随附的Indy 10?

来自分类Dev

在Indy 10中是否可以使用IMAP GetLineResponse?

来自分类Dev

使用tcp indy10进行实时音频流

来自分类Dev

如何使用Indy10 TIdIcmpClient跟踪路由?

来自分类Dev

Indy 10服务器:如何发送JSON响应?

来自分类Dev

Indy10>如何在WriteLn()调用之后等待

来自分类Dev

带Indy 10的Delphi-TCP通讯的最佳方法

来自分类Dev

Delphi 2007 Indy 10找不到SSL库

来自分类Dev

Indy SMTPServer在OnConnect事件中发送错误消息

来自分类Dev

迁移到10.4 Sydney后,Delphi Indy SSL错误