7

I try to upload file into dropbox.
I use dropbox api https://www.dropbox.com/developers/reference/api#files-POST

procedure TDropbox.Upload2;
const
  URL = 'https://api-content.dropbox.com/1/files/dropbox/';
var
  Response: String;
  Params: TIdMultipartFormDataStream;
  https: TIdHTTP;
  SslIoHandler: TIdSSLIOHandlerSocket;
begin
  https := TIdHTTP.Create(nil);
  Params := TIdMultipartFormDataStream.Create();
  try
    SslIoHandler := TIdSSLIOHandlerSocket.Create(https);
    SslIoHandler.SSLOptions.Method := sslvTLSv1;
    SslIoHandler.SSLOptions.Mode := sslmUnassigned;

    https.IOHandler := SslIoHandler;

    Params.AddFormField('oauth_signature_method', 'PLAINTEXT');
    Params.AddFormField('oauth_consumer_key', FAppKey);
    Params.AddFormField('oauth_token', FOAuth.AccessToken);
    Params.AddFormField('oauth_signature', FAppSecret + '&' + FOAuth.AccessTokenSecret);

    Params.AddFile('file', 'C:\test.txt', 'application/octet-stream');

    https.Post(URL + 'test.txt', Params);
  finally
    FreeAndNil(https);
    FreeAndNil(Params);
  end;
end;

I got "400 Bad request".
All tokens are correct (other api works well).
How pass parameters for this api?

barbaris
  • 514
  • 8
  • 25
  • 3
    "Since the entire POST body will be treated as the file, any parameters must be passed as part of the request URL. The request URL should be signed just as you would sign any other OAuth request URL." - maybe, this is the issue? – Nickolay Olshevsky Jan 29 '13 at 09:55
  • maybe. I know how to pass parameters, but how put file into request body? `https.Post(URL + 'test.txt?oauth_signature_method=PLAINTEXT&oauth_consumer_key='+ FAppKey+'&oauth_token='+FOAuth.AccessToken+'oauth_signature='+FAppSecret + '&' + FOAuth.AccessTokenSecret, Params);` - 400 Bad request – barbaris Jan 29 '13 at 10:05
  • Try with this URL, and put file as you did before - via Params.AddFile. – Nickolay Olshevsky Jan 29 '13 at 10:15
  • 1
    Just a note: "We recommend you use /files_put instead due to its simpler interface." – kobik Jan 29 '13 at 10:33
  • 4
    To put the file by itself in the POST body, you simply pass the file to `TIdHTTP.Post()` directly, do not use `TIdMultipartFormDataStream` at all. `TIdHTTP` has several overloaded versions of the `Post()` method. One accepts a filename string as input. Another accepts a non-Multipart `TStream` as input, such as a `TFileStream`. – Remy Lebeau Jan 29 '13 at 18:26

2 Answers2

8

Try this instead:

procedure TDropbox.Upload(const AFileName: String);
const
  API_URL = 'https://api-content.dropbox.com/1/files_put/sandbox/';
var
  URL: String;
  https: TIdHTTP;
  SslIoHandler: TIdSSLIOHandlerSocket;
begin
  URL := API_URL+ExtractFileName(AFileName)
    + '?oauth_signature_method=PLAINTEXT&oauth_consumer_key=' + FAppKey
    + '&oauth_token=' + FOAuth.AccessToken
    + '&oauth_signature=' + FAppSecret + '%26' + FOAuth.AccessTokenSecret;

  https := TIdHTTP.Create(nil);
  try
    SslIoHandler := TIdSSLIOHandlerSocket.Create(https);
    SslIoHandler.SSLOptions.Method := sslvTLSv1;
    SslIoHandler.SSLOptions.Mode := sslmUnassigned;

    https.IOHandler := SslIoHandler;
    https.Post(URL, AFileName);
  finally
    FreeAndNil(https);
  end;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0
  1. Use %26 instead & in oauth_signature parameter. There is two values in one parameter concated by & symbol.
  2. Pass file via TMemoryStream.

    procedure TDropbox.Upload(const AFileName: String);
    const
      API_URL = 'https://api-content.dropbox.com/1/files_put/sandbox/';
    var
      URL: String;
      Stream: TMemoryStream;
      ShortFileName: String;
      https: TIdHTTP;
      SslIoHandler: TIdSSLIOHandlerSocket;
    begin
      if not FileExists(AFileName) then
      begin
        raise EInOutError.CreateFmt('File %s not found', [AFileName]);
      end;
    
      ShortFileName := ExtractFileName(AFileName);
      URL := API_URL+ShortFileName
        + '?oauth_signature_method=PLAINTEXT&oauth_consumer_key=' + FAppKey
        + '&oauth_token=' + FOAuth.AccessToken
        + '&oauth_signature=' + FAppSecret + '%26' + FOAuth.AccessTokenSecret;
    
      https := TIdHTTP.Create(nil);
      Stream := TMemoryStream.Create;
      try
        SslIoHandler := TIdSSLIOHandlerSocket.Create(https);
        SslIoHandler.SSLOptions.Method := sslvTLSv1;
        SslIoHandler.SSLOptions.Mode := sslmUnassigned;
    
        https.IOHandler := SslIoHandler;
        Stream.LoadFromFile(AFileName);
    
        https.Post(URL, Stream);
      finally
        FreeAndNil(Stream);
        FreeAndNil(https);
      end;
    end;
    
barbaris
  • 514
  • 8
  • 25