WWW, WWWForm and SoundCloud

I am trying to upload a file to SoundCloud with the WWW class. When i run the code below i get a response ‘400 Bad Request’. Can someone tell me why or give me some hints what to look for?

Is it even possible to use the WWW class for this?

EDIT:
I looked a bit with Fiddler. I get the following message when running the code:
‘Content-Length mismatch: Request Header indicated 208.662 bytes, but client sent 0 bytes.’

public IEnumerator UploadFileWebClient(FileInfo file)
{
        byte[] fileContents = File.ReadAllBytes(file.FullName);

	WWWForm form = new WWWForm();

	form.AddField("track[title]", "Some title", System.Text.Encoding.UTF8);
	form.AddField("track[sharing]", "private", System.Text.Encoding.UTF8);
	form.AddField("oauth_token", soundCloudToken, System.Text.Encoding.UTF8);
	form.AddField("format", "json", System.Text.Encoding.UTF8);
	form.AddBinaryData("track[asset_data]", fileContents, "0.wav", "application/octet-stream");

	foreach(var header in form.headers)
	{
			Debug.Log ("Header: " + header);
	}

	WWW download = new WWW("https://api.soundcloud.com/tracks", form);
	yield return download;

	if(!string.IsNullOrEmpty(download.error)) 
	{
		Debug.Log ( "Error downloading: " + download.error );
	} 
	else 
	{
		Debug.Log(download.text);
	}
}

UPDATE: the SoundCloud token request (just for the completeness of the question):

public IEnumerator GetTokenAndUploadFile(MonoBehaviour mono, FileInfo file)
	{
		Debug.Log ( "GetTokenAndUploadFile() started");
		ServicePointManager.ServerCertificateValidationCallback = (p1, p2, p3, p4) => true;

		var form = new WWWForm ();
		form.AddField ("client_id", _clientId);
		form.AddField ("client_secret", _clientSecret);
		form.AddField ("grant_type", "password");
		form.AddField ("username", _username);
		form.AddField ("password", _password);

		//Authentication
		string soundCloudTokenRes = "https://api.soundcloud.com/oauth2/token";

		Debug.Log ( "Try to get token");
		WWW download = new WWW(soundCloudTokenRes, form);

		yield return download;
		
		if(!string.IsNullOrEmpty(download.error)) 
		{
			Debug.Log ( "Error downloading: " + download.error );
		} 
		else 
		{
			var tokenInfo = download.text;
			tokenInfo = tokenInfo.Remove(0, tokenInfo.IndexOf("token\":\"") + 8);
			soundCloudToken = tokenInfo.Remove(tokenInfo.IndexOf("\""));
			Debug.Log(string.Format("Token set: {0}", soundCloudToken));
		}
	}

A 400 response means the server got the request, but there was something wrong with the format. Usually the response tells you more, but Unity won’t let you access the response on anything but a 200. Anyway, as far as I can see, there are two problems.

  1. You need to specify the token in an Authorization header.
  2. You’re sending the wrong verb; POST when you want a PUT.
    Dictionary headers = new Dictionary();
    headers.Add("Authorization", "Bearer " + token);
    headers.Add("X-HTTP-Method-Override", "PUT");
    WWW download = new WWW(same_url, form, headers);

Bearer is an OAuth thing. Make sure you get a “token” and not a “code”; a “code” is just used to retrieve a token via a server. (I don’t think there’s any worry of injection attacks here.)

HTTP has several different verbs; ways to call a url. Soundcloud uses GET, POST, PUT and DELETE. The WWW class only supports GET and POST, and you can’t set headers for GET. To get around stupid limitations like Unity’s WWW class has, SoundCloud supports the fairly common nonstandard header X-HTTP-Method-Override. The value for that header should be the (capitalized) verb you want to use.

You need to use System.Collections.Hashtable instead of System.Collections.Generic.Dictionary<string, string> in older versions of Unity.