Question

Good morning.

I'm developing a small media player with built in support for audio recognition using the Echonest API. I've dealt with API's before and know how to submit and parse results, but the other API's provided simple POST/GET examples in their documentation thus opening it up to almost every situation regardless of language or platform.

The Echonest API however, only provides CURL examples. CURL is something I've never dealt with. I'm working in Delphi XE3, or Firemonkey 2 to be specific, and thus there's no built in CURL library or components. There are a few third-party ones available, but I'm not confident they're up to date as they're listing Delphi 6 as being their development environment, and brief searches indicate they're no longer working with modern versions of Delphi (whether this is true or not is a different story).

As I'm wanting to try and keep things as cross-platform as possible to potentially compile an OS X version at a future date, and feel confident in dealing with POST and GET already, how would I go about 'translating' this CURL command into something I could use with Indy (for example);

curl -F "api_key=FILDTEOIK2HBORODV" -F "filetype=mp3" -F "track=@audio.mp3" "http://developer.echonest.com/api/v4/track/upload"

This was taken directly from their API documentation, and is used for uploading a track to their service.

I'm not sure on the specifics regarding CURL and so before I go throwing random data at the service, I felt it best to see whether the SO community can give a brief explanation and example that I can work from. The explanation is much more valuable than the example in any case, but an example may serve well for anyone else who happens to stumble upon a similar problem.

Regards, Scott Pritchard.

Was it helpful?

Solution

The -F option tells curl to POST the provided data using the HTTP "multipart/form-data" Content-Type, which looks like this at the HTTP layer:

POST /api/v4/track/upload HTTP/1.1
Host: developer.echonest.com
Content-Type: multipart/form-data; boundary="boundaryvalue"

--boundaryvalue
Content-Disposition: form-data; name="api_key"

FILDTEOIK2HBORODV
--boundaryvalue
Content-Disposition: form-data; name="filetype"

mp3
--boundaryvalue
Content-Disposition: form-data; name="track"; filename="audio.mp3"
Content-Type: audio/x-mpg

<binary audio data here>
--boundaryvalue--

The Post() method of Indy's TIdHTTP component implements that Content-Type via the TIdMultipartFormDataStream utility class, eg:

uses
  ..., IdHTTP, IdMultipartFormData;

var
  Data: TIdMultipartFormDataStream;
begin
  Data := TIdMultipartFormDataStream.Create;
  try
    Data.AddFormField('api_key', 'FILDTEOIK2HBORODV');
    Data.AddFormField('filetype', 'mp3');
    Data.AddFile('track', 'C:\path to\audio.mp3');
    IdHTTP1.Post('http://developer.echonest.com/api/v4/track/upload', Data);
  finally
    Data.Free;
  end;
end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top