I have to post a jpg file using TIdHTTP component (Indy 10). What I need is to upload a file to a Drupal 8 field. I can do it with Advanced Rest Client following this documentation:
https://www.drupal.org/docs/8/core/modules/jsonapi-module/file-uploads
https://www.drupal.org/node/3024331#comment-13387295
But I'm tring to do it with Delphi 2010 and Indy 10 without success. I always get a "415 Unsupported media type" error with this detail:
"No route found that matches "Content-Type: multipart/form-data".
This is the code I use:
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;
You can't post the file using TIdMultiPartFormDataStream
, because the server is explicitly telling you that it does not support multipart/form-data
requests (calling TIdHTTP.Post()
with a TIdMultiPartFormDataStream
overwrites the Request.ContentType
).
You will have to post the file use a plain vanilla TStream
instead, such as 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;
Alternatively, TIdHTTP
has an overload of Post()
that takes a file path as input:
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;