如何使用 Indy10 Http post 二进制 jpg 文件?

How to post binary jpg file using Indy10 Http?

我必须 post 使用 TIdHTTP 组件 (Indy 10) 的 jpg 文件。我需要的是将文件上传到 Drupal 8 字段。我可以按照此文档使用 Advanced Rest Client 来完成此操作:

https://www.drupal.org/docs/8/core/modules/jsonapi-module/file-uploads

https://www.drupal.org/node/3024331#comment-13387295

但我想用 Delphi 2010 和 Indy 10 来做,但没有成功。我总是收到“415 Unsupported media type”错误,详细信息如下:

"No route found that matches "Content-Type: multipart/form-data".

这是我使用的代码:

var
    response: string;
    Params: TIdMultiPartFormDataStream;
begin
    Result := '';

    IdHTTP1.ConnectTimeout := 10000;
    IdHTTP1.Request.Clear;
    IdHTTP1.Request.CustomHeaders.Clear;
    IdHTTP1.Request.BasicAuthentication := false;
    IdHTTP1.Request.ContentType := 'application/octet-stream';
    IdHTTP1.Request.Accept := 'application/vnd.api+json';
    IdHTTP1.Request.ContentLanguage := 'es';
    IdHTTP1.Request.CustomHeaders.AddValue('api-key', 'my_api_key_here');
    IdHTTP1.Request.ContentDisposition:= 'file; filename="testimage.jpg"';

    IdHTTP1.Request.Charset := 'utf-8';
    IdHTTP1.AllowCookies := True;
    IdHTTP1.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36';
    IdHTTP1.HandleRedirects := True;

    Params := TIdMultiPartFormDataStream.Create;
    try
        try
            Params.AddFile('testimage.jpg','c:\tmp\testimage.jpg','application/octet-stream').ContentTransfer:='binary';
            response:= IdHTTP1.Post('<my_url_to_the_field_as_instructions>', Params);
        except
            on E: Exception do
            begin
                memo1.Lines.add('Error ' + E.message);
            end;
        end;
    finally
        Params.Free;
    end;

您不能 post 使用 TIdMultiPartFormDataStream 的文件,因为服务器明确告诉您它不支持 multipart/form-data 请求(调用 TIdHTTP.Post() TIdMultiPartFormDataStream 覆盖 Request.ContentType).

您将不得不 post 文件改用普通的 TStream,例如 TFileStream:

var
  response: string;
  PostData: TStream;
begin
  Result := '';

  IdHTTP1.ConnectTimeout := 10000;
  IdHTTP1.Request.Clear;
  IdHTTP1.Request.BasicAuthentication := false;
  IdHTTP1.Request.ContentType := 'application/octet-stream';
  IdHTTP1.Request.Accept := 'application/vnd.api+json';
  IdHTTP1.Request.ContentLanguage := 'es';
  IdHTTP1.Request.CustomHeaders.AddValue('api-key', 'my_api_key_here');
  IdHTTP1.Request.ContentDisposition := 'file; filename="testimage.jpg"';

  IdHTTP1.AllowCookies := True;
  IdHTTP1.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36';
  IdHTTP1.HandleRedirects := True;

  PostData := TFileStream.Create('<path_to>\testimage.jpg', fmOpenRead or fmShareDenyWrite);
  try
    try
      response := IdHTTP1.Post('<my_url_to_the_field_as_instructions>', PostData);
    except
      on E: Exception do
      begin
        Memo1.Lines.Add('Error ' + E.message);
      end;
    end;
  finally
    PostData.Free;
  end;
end;

或者,TIdHTTP 有一个 Post() 的重载,它将文件路径作为输入:

var
  response: string;
begin
  Result := '';

  IdHTTP1.ConnectTimeout := 10000;
  IdHTTP1.Request.Clear;
  IdHTTP1.Request.BasicAuthentication := false;
  IdHTTP1.Request.ContentType := 'application/octet-stream';
  IdHTTP1.Request.Accept := 'application/vnd.api+json';
  IdHTTP1.Request.ContentLanguage := 'es';
  IdHTTP1.Request.CustomHeaders.AddValue('api-key', 'my_api_key_here');
  IdHTTP1.Request.ContentDisposition := 'file; filename="testimage.jpg"';

  IdHTTP1.AllowCookies := True;
  IdHTTP1.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36';
  IdHTTP1.HandleRedirects := True;

  try
    response := IdHTTP1.Post('<my_url_to_the_field_as_instructions>', '<path_to>\testimage.jpg');
  except
    on E: Exception do
    begin
      Memo1.Lines.Add('Error ' + E.message);
    end;
  end;
end;