Search code examples
delphidropboxindydelphi-2009indy10

Idhttp Indy upload to Dropbox with utf-8 file name


I'm trying to upload a file to Dropbox using Indy 10 and XE8. While file name like 'file.txt' it works OK, but with 'файл.txt' or so, I have '????.txt' on DropBox. I read about parameters with utf-8 but it is don't work with headers :-(.

How can I upload a file and save utf-8 file name?

procedure TSaveFilterForm.TestButtonClick(Sender: TObject);
const
  URL = 'https://content.dropboxapi.com/2/files/upload';
var
  IdHTTP: TIdHTTP;
  Source: TFileStream;
  Res: String;
begin                           
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdHTTP.HandleRedirects := True;
    IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    IdHTTP.Request.BasicAuthentication := False;
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + AccessToken;
    IdHTTP.Request.ContentType := 'application/octet-stream';
    Source := TFileStream.Create('c:\test.txt', fmOpenRead);

    IdHTTP.Request.CustomHeaders.Values['Dropbox-API-Arg'] :=
      Format('{ "path": "%s", "mode": "overwrite"}',
        ['/файл.txt']); // Dropbox => ????.txt
    try
      Res := IdHTTP.Post(URL, Source);
    finally
      Source.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;

Solution

  • For these calls with the parameters in the header, you need to escape these characters. That is, when you use the “Dropbox-API-Arg” header, you need to make it “HTTP header safe”. This means using JSON-style “\uXXXX” escape codes for the character 0x7F and all non-ASCII characters.

    Some, but not all, languages/libraries do this for you. For example, for JavaScript, to do this yourself you could do something like this:

    var charsToEncode = /[\u007f-\uffff]/g;
    
    function http_header_safe_json(v) {
     return JSON.stringify(v).replace(charsToEncode,
     function(c) {
     return '\\u' + ('000' + c.charCodeAt(0).toString(16)).slice(-4);
     }
     );
    }
    

    and then something like:

    'Dropbox-API-Arg': http_header_safe_json({ path: dropboxFilePath })
    

    It sounds like your platform doesn't do that for you, so you'll want to implement this in your code.