我正在尝试使用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已断开连接。
您的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>
序列分隔,并且CRLF
在TFileStream
数据和紧跟其后的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
:
如果包含两个以上的部分,则该请求将被拒绝。每个部分都必须
name
在Content-Disposition
标头中指定一个值,以指示它是哪个部分。部件可以采用任何顺序,但应首先指定元数据部件。
但是,同一文档中给出的示例正在使用multipart/related
,就像您的代码一样。Microsoft / OneDrive论坛和各种博客中都有关于是否使用multipart/form-data
或multipart/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] 删除。
我来说两句