Unity3D,C#和上传曲目到SoundCloud

时间:2015-05-24 13:44:21

标签: android unity3d upload soundcloud

我正在使用Unity3D中的一个应用程序,它可以将曲目上传到SoundCloud。我已经研究了一段时间,但我无法让它工作。我正在使用HttpWebRequest来请求SoundCloud,这在Unity for Windows上运行良好。但是当我在我的Android设备上尝试它时,我得到以下消息:'请求实体包含无效的字节序列。请传送有效的UTF-8。'。

以下是我使用的代码部分(从互联网上的某个地方获取)。

我确定我在Windows上上传了与Android相同的文件并向RequestBin发出了请求。现在,当我比较两者时,我注意到原始数据几乎完全相同,除了结尾:

结束Windows:ÿàþ³þDþÿýëýÅýÙý

结束Android:ÿàþ³þDþÿýëýÅýÙý[FF]þÞýþûýCþxþZþ{þ

正如您所看到的,在Android上有更多数据。有人可以向我解释这里发生了什么吗?

我从Unity社区的帖子开始,现在在这里尝试。 Here您可以在团结网站上找到我的问题以获取更多信息。

public class SoundCloudScript {

//Enter app credentials from here http://soundcloud.com/you/apps
private const string _clientId = "xxx";
private const string _clientSecret = "xxx";
//enter username and password a soundcloud user, e.g. your own credentials
private const string _username = "xxx";
private const string _password = "xxx";

private string soundCloudToken;

//private WebClient _webclient = new WebClient();

public string Status { get; set; }

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));

        UploadFile(file);
    }
}

public void UploadFile(FileInfo file)
{
    Debug.Log ("Start uploading!");

    ServicePointManager.Expect100Continue = false;
    var request = WebRequest.Create("https://api.soundcloud.com/tracks/") as HttpWebRequest;
    //some default headers
    request.Accept = "*/*";
    request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");
    request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
    request.Headers.Add("Accept-Language", "en-US,en;q=0.8,ru;q=0.6");

    //file array
    var files = new UploadFile[] 
    { 
        new UploadFile(file.FullName, "track[asset_data]", "application/octet-stream") 
    };

    //other form data
    var form = new System.Collections.Specialized.NameValueCollection();
    form.Add("track[title]", "Some title");
    form.Add("track[sharing]", "private");
    form.Add("oauth_token", soundCloudToken);
    form.Add("format", "json");

    try
    {
        using (var response = HttpUploadHelper.Upload(request, files, form))
        {
            using (var reader = new StreamReader(response.GetResponseStream()))
            {
                reader.ReadToEnd();
            }
        }
        Debug.Log ("Upload success!");
    }
    catch (WebException wex) {
        if (wex.Response != null) {
            using (var errorResponse = (HttpWebResponse)wex.Response) {
                using (var reader = new StreamReader(errorResponse.GetResponseStream())) {
                    string error = reader.ReadToEnd();
                    Debug.Log ("Error(1/2): Message: " + wex.Message);
                    Debug.Log ("Error(2/2): " + error);
                    //TODO: use JSON.net to parse this string and look at the error message
                }
            }
        }

    }

    //return "Nothing...";
    }
}

public class StreamMimePart : MimePart
{
    Stream _data;

    public void SetStream(Stream stream)
    {
        _data = stream;
    }

    public override Stream Data
    {
        get
        {
            return _data;
        }
    }
}

public abstract class MimePart
{
NameValueCollection _headers = new NameValueCollection();
byte[] _header;

public NameValueCollection Headers
{
    get { return _headers; }
}

public byte[] Header
{
    get { return _header; }
}

public long GenerateHeaderFooterData(string boundary)
{
    StringBuilder sb = new StringBuilder();

    sb.Append("--");
    sb.Append(boundary);
    sb.AppendLine();
    foreach (string key in _headers.AllKeys)
    {
        sb.Append(key);
        sb.Append(": ");
        sb.AppendLine(_headers[key]);
    }
    sb.AppendLine();

    _header = Encoding.UTF8.GetBytes(sb.ToString());

    return _header.Length + Data.Length + 2;
}

public abstract Stream Data { get; }
}

public class StringMimePart : MimePart
{
Stream _data;

public string StringData
{
    set
    {
        _data = new MemoryStream(Encoding.UTF8.GetBytes(value));
    }
}

public override Stream Data
{
    get
    {
        return _data;
    }
}
}

public class HttpUploadHelper
{
private HttpUploadHelper()
{ }

public static string Upload(string url, UploadFile[] files, NameValueCollection form)
{
    HttpWebResponse resp = Upload((HttpWebRequest)WebRequest.Create(url), files, form);

    using (Stream s = resp.GetResponseStream())
        using (StreamReader sr = new StreamReader(s))
    {
        return sr.ReadToEnd();
    }
}

public static HttpWebResponse Upload(HttpWebRequest req, UploadFile[] files, NameValueCollection form)
{
    List<MimePart> mimeParts = new List<MimePart>();

    try
    {
        foreach (string key in form.AllKeys)
        {
            StringMimePart part = new StringMimePart();

            part.Headers["Content-Disposition"] = "form-data; name=\"" + key + "\"";
            part.StringData = form[key];

            mimeParts.Add(part);
        }

        int nameIndex = 0;

        foreach (UploadFile file in files)
        {
            StreamMimePart part = new StreamMimePart();

            if (string.IsNullOrEmpty(file.FieldName))
                file.FieldName = "file" + nameIndex++;

            part.Headers["Content-Disposition"] = "form-data; name=\"" + file.FieldName + "\"; filename=\"" + file.FileName + "\"";
            part.Headers["Content-Type"] = file.ContentType;

            part.SetStream(file.Data);

            mimeParts.Add(part);
        }

        string boundary = "----------" + DateTime.Now.Ticks.ToString("x");

        req.ContentType = "multipart/form-data; boundary=" + boundary;
        req.Method = "POST";

        long contentLength = 0;

        byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");

        foreach (MimePart part in mimeParts)
        {
            contentLength += part.GenerateHeaderFooterData(boundary);
        }

        req.ContentLength = contentLength + _footer.Length;

        Debug.Log ("ContentLength: " + req.ContentLength);

        byte[] buffer = new byte[8192];
        byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
        int read;

        foreach(var header in req.Headers)
        {
            Debug.Log(header);
        }

        using (Stream s = req.GetRequestStream())
        {
            foreach (MimePart part in mimeParts)
            {
                s.Write(part.Header, 0, part.Header.Length);

                while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0)
                {
                    s.Write(buffer, 0, read);
                    Debug.Log ("Buffer: >>" + System.Text.Encoding.UTF8.GetString(buffer) + "<<");
                }

                //Debug.Log ("Buffer: " + System.Text.Encoding.UTF8.GetString(buffer));

                part.Data.Dispose();

                s.Write(afterFile, 0, afterFile.Length);
                Debug.Log ("Buffer-End: >>" + System.Text.Encoding.UTF8.GetString(afterFile) + "<<");
            }

            s.Write(_footer, 0, _footer.Length);

            Debug.Log ("Footer: >>" + System.Text.Encoding.UTF8.GetString(_footer) + "<<");
        }

        return (HttpWebResponse)req.GetResponse();
    }
    catch (Exception e)
    {
        Debug.Log ("Crash! Message: " + e.Message);
        foreach (MimePart part in mimeParts)
            if (part.Data != null)
                part.Data.Dispose();

        throw;
    }
}
}

public class UploadFile
{
Stream _data;
string _fieldName;
string _fileName;
string _contentType;

public UploadFile(Stream data, string fieldName, string fileName, string contentType)
{
    _data = data;
    _fieldName = fieldName;
    _fileName = fileName;
    _contentType = contentType;
}

public UploadFile(string fileName, string fieldName, string contentType)
    : this(File.OpenRead(fileName), fieldName, Path.GetFileName(fileName), contentType)
{ }

public UploadFile(string fileName)
    : this(fileName, null, "application/octet-stream")
{ }

public Stream Data
{
    get { return _data; }
    set { _data = value; }
}

public string FieldName
{
    get { return _fieldName; }
    set { _fieldName = value; }
}

public string FileName
{
    get { return _fileName; }
    set { _fileName = value; }
}

public string ContentType
{
    get { return _contentType; }
    set { _contentType = value; }
}
}

1 个答案:

答案 0 :(得分:0)

它正在工作!!问题是,在某些时候我使用StringBuilder.AppendLine()来添加一个新行。这在Windows上工作正常,但在Android上它没有工作......(我想出来因为Windows和Android的Content-Length不一样。)

我修复它而不是使用&#39; StringBuilding.AppendLine()&#39;,我使用&#39; StringBuilder.Append(&#34; \ r \ n&#34;)&#39;