Delphi - 使用 TIdMultipartFormDataStream 的 idHTTP 上传文件
Delphi - idHTTP upload file using TIdMultipartFormDataStream
我正在尝试使用 TIdHTTP
上传文件。问题是当请求发送到服务器时访问令牌被更改。
我使用的访问令牌是 fJNhDM6TlcpeVmD8h3jFuPJS71sxwZB8bZBXajTRB5TNAcRa6PNXfv4J7mPxIvMdMhjy7oKdTLbsRYthpBCCqGVkj4vlojJ4BRBkLAVIBJ1DZAnMZD
API returns
HTTP/1.1 400 Bad Request
OAuth "invalid_token" "Malformed access token fJNhDM6TlcpeVmD8h3jFu=\r\nPJS71sxwZB8bZBXajTRB5TNAcRa6PNXfv4J7mPxIvMdMhjy7oKdTLbsRYthpBCCqGVkj4v=\r\nlojJ4BRBkLAVIBJ1DZAnMZD"
=\r\n
两次添加到我的令牌中。
我的代码是:
function TFoo.Post(const AToken, guID, AMessage, AImageFileName: string): Boolean;
var
lParam : TIdMultipartFormDataStream;
begin
Result := False;
if not FileExists(AImageFileName) then begin
LastError := 'File not found ' + AImageFileName;
Exit;
end;
ProxyCheck;
lParam := TIdMultipartFormDataStream.Create;
try
lParam.AddFormField('message', AMessage);
lParam.AddFormField('access_token', AToken);
lParam.AddFile('source', AImageFileName);
idHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
try
idHTTP.Post( UrlAPI + guID + '/photos', lParam);
Result := True;
except;
LastError := idHTTP.ResponseText + sLineBreak + idHTTP.Response.WWWAuthenticate.Text;
end;
finally
lParam.Free;
end;
end;
我在这里错过了什么?
默认情况下,AddFormField()
将 TIdFormDataField.ContentTransfer
属性 设置为 MIME 的 quoted-printable
格式。这就是额外 =\r\n
的来源。这是一个 "soft" 换行符,每 76 个字符被 quoted-printable
插入。任何支持 quoted-printable
的服务器都会在解码期间删除 "soft" 换行符。但也许你的服务器没有。
如果要禁用 quoted-printable
行为,可以将 ContentTransfer
属性 设置为:
一个空字符串:
lParam.AddFormField('access_token', AToken).ContentTransfer := '';
'7bit'
(因为它不包含任何非 ASCII 字符):
lParam.AddFormField('access_token', AToken).ContentTransfer := '7bit';
'8bit'
或 binary
:
lParam.AddFormField('access_token', AToken).ContentTransfer := '8bit';
lParam.AddFormField('access_token', AToken).ContentTransfer := 'binary';
在这种情况下,我建议#1。
附带说明一下,在发布 TIdMultipartFormDataStream
时不要设置 HTTP 内容类型。您不仅开始时使用了错误的媒体类型(应该是 multipart/form-data
),而且 TIdMultipartFormDataStream
版本的 Post()
无论如何都会简单地覆盖它。
function TFoo.Post(const AToken, guID, AMessage, AImageFileName: string): Boolean;
var
lParam : TIdMultipartFormDataStream;
begin
Result := False;
if not FileExists(AImageFileName) then begin
LastError := 'File not found ' + AImageFileName;
Exit;
end;
ProxyCheck;
lParam := TIdMultipartFormDataStream.Create;
try
lParam.AddFormField('message', AMessage);
lParam.AddFormField('access_token', AToken).ContentTransfer := '';
lParam.AddFile('source', AImageFileName);
try
idHTTP.Post(UrlAPI + guID + '/photos', lParam);
Result := True;
except;
LastError := idHTTP.ResponseText + sLineBreak + idHTTP.Response.WWWAuthenticate.Text;
end;
finally
lParam.Free;
end;
end;
我正在尝试使用 TIdHTTP
上传文件。问题是当请求发送到服务器时访问令牌被更改。
我使用的访问令牌是 fJNhDM6TlcpeVmD8h3jFuPJS71sxwZB8bZBXajTRB5TNAcRa6PNXfv4J7mPxIvMdMhjy7oKdTLbsRYthpBCCqGVkj4vlojJ4BRBkLAVIBJ1DZAnMZD
API returns
HTTP/1.1 400 Bad Request
OAuth "invalid_token" "Malformed access token fJNhDM6TlcpeVmD8h3jFu=\r\nPJS71sxwZB8bZBXajTRB5TNAcRa6PNXfv4J7mPxIvMdMhjy7oKdTLbsRYthpBCCqGVkj4v=\r\nlojJ4BRBkLAVIBJ1DZAnMZD"
=\r\n
两次添加到我的令牌中。
我的代码是:
function TFoo.Post(const AToken, guID, AMessage, AImageFileName: string): Boolean;
var
lParam : TIdMultipartFormDataStream;
begin
Result := False;
if not FileExists(AImageFileName) then begin
LastError := 'File not found ' + AImageFileName;
Exit;
end;
ProxyCheck;
lParam := TIdMultipartFormDataStream.Create;
try
lParam.AddFormField('message', AMessage);
lParam.AddFormField('access_token', AToken);
lParam.AddFile('source', AImageFileName);
idHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
try
idHTTP.Post( UrlAPI + guID + '/photos', lParam);
Result := True;
except;
LastError := idHTTP.ResponseText + sLineBreak + idHTTP.Response.WWWAuthenticate.Text;
end;
finally
lParam.Free;
end;
end;
我在这里错过了什么?
默认情况下,AddFormField()
将 TIdFormDataField.ContentTransfer
属性 设置为 MIME 的 quoted-printable
格式。这就是额外 =\r\n
的来源。这是一个 "soft" 换行符,每 76 个字符被 quoted-printable
插入。任何支持 quoted-printable
的服务器都会在解码期间删除 "soft" 换行符。但也许你的服务器没有。
如果要禁用 quoted-printable
行为,可以将 ContentTransfer
属性 设置为:
一个空字符串:
lParam.AddFormField('access_token', AToken).ContentTransfer := '';
'7bit'
(因为它不包含任何非 ASCII 字符):lParam.AddFormField('access_token', AToken).ContentTransfer := '7bit';
'8bit'
或binary
:lParam.AddFormField('access_token', AToken).ContentTransfer := '8bit';
lParam.AddFormField('access_token', AToken).ContentTransfer := 'binary';
在这种情况下,我建议#1。
附带说明一下,在发布 TIdMultipartFormDataStream
时不要设置 HTTP 内容类型。您不仅开始时使用了错误的媒体类型(应该是 multipart/form-data
),而且 TIdMultipartFormDataStream
版本的 Post()
无论如何都会简单地覆盖它。
function TFoo.Post(const AToken, guID, AMessage, AImageFileName: string): Boolean;
var
lParam : TIdMultipartFormDataStream;
begin
Result := False;
if not FileExists(AImageFileName) then begin
LastError := 'File not found ' + AImageFileName;
Exit;
end;
ProxyCheck;
lParam := TIdMultipartFormDataStream.Create;
try
lParam.AddFormField('message', AMessage);
lParam.AddFormField('access_token', AToken).ContentTransfer := '';
lParam.AddFile('source', AImageFileName);
try
idHTTP.Post(UrlAPI + guID + '/photos', lParam);
Result := True;
except;
LastError := idHTTP.ResponseText + sLineBreak + idHTTP.Response.WWWAuthenticate.Text;
end;
finally
lParam.Free;
end;
end;