简体   繁体   中英

Dropbox API HTTP Unity3d upload download

Since there is no official support for Unity3d and Dropbox I'm using the HTTP API. I was able to do both the oauth2/authorize with the code flow (by using Application.OpenURL in Unity3d), and the oauth2/token Post part (so I was able to login and get the code that I got from the oauth2/authorize).

Problem is I don't really know how to upload and download files. What I tried (this code is inside a Coroutine):

Dictionary<string, string> postHeader = new Dictionary<string, string>();
postHeader.Add("Authorization", "Bearer <code>");
postHeader.Add("Dropbox-API-Arg", "{\"path\": \"/uploadtry.json\",\"mode\": \"overwrite\",\"autorename\": true,\"mute\": false}");
postHeader.Add("Content-Type", "application/octet-stream");
byte[] myData = System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(Application.persistentDataPath + "/" + "uploadtry.json"));
using (WWW www = new WWW("https://content.dropboxapi.com/2/files/upload", myData, postHeader)) {
  yield return www;
  if (www.error != null) {
    Debug.Log(www.error);
  } else {
    Debug.Log("Success! " + www.text);
  }
}

I get Error 400 from this.

Dropbox docs say

curl -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer <code>" \
--header "Dropbox-API-Arg: {\"path\": \"/Homework/math/Matrices.txt\",\"mode\": \"add\",\"autorename\": true,\"mute\": false}" \
--header "Content-Type: application/octet-stream" \
--data-binary @local_file.txt

I'm sure that my post is right because I've done the same for the login part. I'm sure that the bearer header is right. I'm not sure that the path part of Dropbox-API-Arg is right... my app only got access to it's own folder but I don't really know if I should always use the full path... I tried it anyway but I got the same error (I copied the path from "Applicazioni" italian for Applications created automatically after the authorization part and MyAppName... I have not tried to add /home/ to the path). I'm not sure if overwrite is compatible with autorename true. I'm not sure if I have to use application/octet-stream or application/json but I tried both and got the same Error 400.

So I think the problem can be that --data-binary. Right now I read all file text and I convert it to an array of byte... usually this works for -d (data) but maybe this is wrong for --data-binary.

I also tried to generate the access token from dropbox (the temporary solution to avoid the authorization part the only work with your own account... Because I don't know if the bearer code can expire) but this was not helpful. I still got error 400.

With download:

https://content.dropboxapi.com/2/files/download

I don't get any error. But I have no idea how to decide the download folder so I don't get any file.

https://www.dropbox.com/developers/documentation/http/documentation#files-download

I don't understand how can I specify the download folder in the (GET?)? I'm really confused.

EDIT. I tried curl from a linux terminal (at home I use Windows so I don't have curl), and I was able to upload and download with curl (I was right about the path it start from the application folder so /uploadtry.json is good. the Bearer works. overwrite is compatible with autorename true and Content-type application/octet-stream is good. Also the get only print the file so I don't really know why it didn't work with no errors (but it was late, maybe for the download the problem was an error in the code, I will try again today).

The only real difference is that in Unity I read the file as a text->convert to an array of byte->send in the body... In curl I use --data-binary @path/to/file.json Maybe it's because there is no name if I pass a simple array of bytes... I don't really know. I will update if I found a solution, but if you have an idea I appreciate.

EDIT2. Tried the download again still not working. Error 400 Bad request

from curl

curl -X POST https://content.dropboxapi.com/2/files/download     --header "Authorization: Bearer <code>" --header "Dropbox-API-Arg: {\"path\": \"/prova.json\"}"

this is working and return a string to the terminal.

on Unity3d

Dictionary<string, string> postHeader = new Dictionary<string, string>();
postHeader.Add("Authorization", "Bearer <code>");
postHeader.Add("Dropbox-API-Arg", "{\"path\": \"/prova.json\"}");
using (WWW www = new WWW("https://content.dropboxapi.com/2/files/download", null, postHeader)){
    yield return www;
    if (www.error != null){
        Debug.Log(www.error);
    }else{
        Debug.Log("Success! " + www.text);
    }
}

this is not working.

I don't really know what I'm doing wrong here.

EDIT3.

For some reason the upload code is actually working. Maybe it's the OS, or maybe it's the unity version (they updated it yesterday, but at home I'm still using the old version...) anyway, right now the only problem is that I still don't know how to download.

EDIT4.

Ok New problem. I tried with the UnityWebRequest class (that for Post does not work) and I changed to a Get (since with curl is still working. With this code the download return Success.... but with an empty file

using (UnityWebRequest www = UnityWebRequest.Get("https://content.dropboxapi.com/2/files/download"))
    {
        www.SetRequestHeader("Authorization", "Bearer <code>");
        www.SetRequestHeader("Dropbox-API-Arg", "{\"path\": \"/prova.json\"}");
        yield return www;
        if (www.error != null)
        {
            Debug.Log(www.error);
        }
        else
        {
            Debug.Log("Success! " + www.downloadHandler.data.Length);
        }
    }

Ok, thanks to Greg suggesion I was able to think about something to seach on google for the download problem. Like I said the upload works (even on the 2018.1 version of Unity3d. I will upload after this post to see if 2018.2 still works). I don't really know why yesterday I was not able to upload files (maybe my code was wrong for example in the url and I didn't notice).

Anyway, for the download part I was finally able to understand what was the problem: the Content-Type. Dropbox, for the download, require an empty "" content type (but I don't see it in the docs, I was able to find this information here: Dropbox download file API stopped working with 400 error ).

From there the solution was easy. I used again the WWW class (UnityWebRequest Post is still broken for some reason), and with this code I was able to get the text of my json file (just added an header):

Dictionary<string, string> postHeader = new Dictionary<string, string>();
    postHeader.Add("Authorization", "Bearer <code>");
    postHeader.Add("Dropbox-API-Arg", "{\"path\": \"/provaupload.json\"}");
    postHeader.Add("Content-Type", "");
    using (WWW www = new WWW("https://content.dropboxapi.com/2/files/download", null, postHeader)) {
        yield return www;
        if (www.error != null) {
            Debug.Log(www.error + " " + www.text);
        } else {
            Debug.Log("Success! " + www.text);
        }
    }

Finally I can complete my save cloud solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM