Mark Elder
Mark Elder

Reputation: 4127

Forcing TDownloadURL.DownloadRawBytes to skip string conversion when no ContentType Header

I'm trying to use TDownloadURL.DownloadRawBytes from the Rest.Client unit to download a PDF file from an Amazon S3 bucket.

My problem seems to be an empty ContentType returned with the file. I don't control the server side and don't have any way to get them to correctly set the ContentType.

TRESTRequest.Execute looks at the returned context type, if it is empty then it forces the MimeKind to TMimeTypes.TKind.Text. That in turn forces the returned Bytes to be converted to a string.

There is a way to pass in a different string encoding, but not a way to force a MimeType or to skip the string conversion.

Without that when I Execute the request I get the following error:

Project raised exception class EEncodingError with message 'No mapping for the Unicode character exists in the target multi-byte code page'.

Upvotes: 2

Views: 117

Answers (1)

Mark Elder
Mark Elder

Reputation: 4127

Here is my modified version of DownloadRawBytes. I needed the response saved to a file so it write is out directly instead of returning a stream.

Based on Remy's comment I set the FallbackCharsetEncoding, both CP437 and ISO-8859-1 worked for me.

procedure TMapRightIntegration.SaveAttachment(AUrl, AFileName: String);
var
  FileStream: TFileStream;
  Request: TRESTRequest;
  Client: TRESTClient;
  Response: TCustomRESTResponse;

begin
  Client := TRESTClient.Create(AUrl);
  try
    Request := TRESTRequest.Create(Client);
    Request.SynchronizedEvents := False;

    // We don't need the string, this encoding will ensure the 
    // conversion from binary will not fail on any byte.
    Client.FallbackCharsetEncoding := 'CP437';

    Request.Execute;
    Response := Request.Response;

    if Response.StatusCode >= 300 then
      raise ERequestError.Create(Response.StatusCode, Response.StatusText, Response.Content);

    if Response.RawBytes = nil then
      raise Exception.Create('RawBytes is nil');

    FileStream := TFileStream.Create(AFileName, fmCreate);
    try
      FileStream.WriteBuffer(Response.RawBytes[0], Length(Response.RawBytes));
    finally
      FileStream.Free;
    end;

  finally
    Client.Free;
  end;
end;

Upvotes: 1

Related Questions