【问题标题】:How to set the boundary of a multipart request using TRestRequest?如何使用 TRESTRequest 设置多部分请求的边界?
【发布时间】:2017-07-05 21:37:13
【问题描述】:

我正在尝试使用 Delphi 的 Rest 组件,但在上传流时卡住了。例如,在 Indy 组件上,我需要添加 MultiPartFormDataStream,在请求内容类型上,我需要设置边界。但是,我无法在 TRESTClient 和 TRESTRequest 上重现它。 代码如下:

//Fields
    rCliTest: TRESTClient;
    rReqTest: TRESTRequest;
    rRespTest: TRESTResponse;

procedure TForm46.btn1Click(Sender: TObject);
var
  StreamContent: TMemoryStream;
begin
  StreamContent := TMemoryStream.Create;
  img1.Picture.Graphic.SaveToStream(StreamContent);

  rCliTest.BaseURL := 'http://petstore.swagger.io/v2/pet/33/uploadImage';
  rCliTest.ContentType := 'application/json';

  rReqTest.Method := TRESTRequestMethod.rmPOST;
  rReqTest.AddParameter('additionalMetadata', 'Tets');
  rReqTest.AddBody(StreamContent, ctMULTIPART_FORM_DATA);

  rReqTest.Execute;

  Caption := rRespTest.Content;
end;

当我尝试执行时出现此错误:

{code":400,"type":"unknown","message":"org.jvnet.mimepull.MIMEParsingException: 缺少起始边界"}

这是用作实现代码的基础卷曲:

curl -X POST --header 'Content-Type: multipart/form-data' --header 'Accept: application/json'
    --header 'Authorization: Bearer 3d9979829200e7cc7e6e6ac039f75e01' -F additionalMetadata=rodrigo
    'http://petstore.swagger.io/v2/pet/33/uploadImage'

更新

  1. 目前我使用的是 Delphi Seattle,但之前我使用的是 Delphi X5 和 Delphi X5 无法像我一样发送流 想。
  2. 我尝试使用 PostMan 和 Advanced Rest Client(ARC,它是 google chrome 扩展程序)创建相同的场景。在 PostMan 上我可以让它工作,但在 ARC 上我不能。要检查发送到我的 RestApi 的内容,我使用 Fiddler from Telerik,这是一种线鲨,但适用于 RestClients。 我从 Fiddler 那里得到的信息来自:

    PostMan 请求(有效):

如果我像这样使用 Delphi 代码,我会收到错误 415:

但如果我将请求格式更改为 multipart_form_data,我会收到此错误和以下输出:

400
{"code":400,"type":"unknown","message":"org.jvnet.mimepull.MIMEParsingException: 缺少起始边界"}

【问题讨论】:

  • Indy 的TIdMultiPartFormDataStream 生成随机边界。 TIdHTTP.Post() 检索该边界并将其放入您的 Content-Type 标头中。
  • rCliTest.ContentType := 'application/json'; 是错误的。应该是'multipart/form-data'。您没有发送 JSON 帖子。

标签: delphi


【解决方案1】:

根据TRESTRequestParameterKind 文档:

pkREQUESTBODY:参数值将用作请求正文。 如果存在多个此类参数,则请求将使用多部分正文

试试类似的方法:

procedure TForm46.btn1Click(Sender: TObject);
var
  StreamContent: TMemoryStream;
begin
  StreamContent := TMemoryStream.Create;
  try
    img1.Picture.Graphic.SaveToStream(StreamContent);
    StreamContent.Position:= 0;

    rCliTest.BaseURL := 'http://petstore.swagger.io/v2/pet/33/uploadImage';    
    rCliTest.ContentType := 'multipart/form-data';

    rReqTest.Method := TRESTRequestMethod.rmPOST;
    rReqTest.AddParameter('additionalMetadata', 'Test',
      TRESTRequestParameterKind.pkREQUESTBODY);    
    rReqTest.Params.AddItem('file', StreamContent,
      TRESTRequestParameterKind.pkREQUESTBODY,
      [TRESTRequestParameterOption.poDoNotEncode],
      TRESTContentType.ctAPPLICATION_OCTET_STREAM);

    rReqTest.Execute;

    Caption := rRespTest.Content;
  finally
    StreamContent.Free;
  end;
end;

【讨论】:

  • 我认为是版本问题。我正在使用 Delphi XE5,但没有带有参数的“AddItem”。我有这个:函数 AddItem: TRESTRequestParameter;超载;函数 AddItem(const AName, AValue: string; AKind: TRESTRequestParameterKind; AOptions: TRESTRequestParameterOptions = []): TRESTRequestParameter;函数 AddItem(const AName, AValue: string): TRESTRequestParameter;函数 AddItem(const AName, AValue: string; const AKind: TRESTRequestParameterKind; const AOptions: TRESTRequestParameterOptions; AContentType: TRESTContentType): TRESTRequestParameter;
  • "我正在使用 Delphi XE5" - 这是应该包含在您的问题中的重要信息。 TBytesTStream 重载已在西雅图 10.0 中添加。在 XE5 中,您可能无法发送包含文件的 multipart/form-data 帖子。
  • 现在我在 Delphi Seattle 上进行测试。使用此代码我得到错误 415,不支持的媒体类型。
  • @RodrigoFariasRezino 实际的 HTTP 请求是什么样的?更糟糕的是,您可以放弃TRESTClient 并返回TIdHTTP
  • 我真的很想使用你的组件 Remy,这些默认值.......
猜你喜欢
  • 2017-09-25
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2018-12-18
  • 2012-10-25
  • 2018-10-01
  • 2013-09-20
相关资源
最近更新 更多