简体   繁体   中英

Google Drive API upload HTTP Multipart Unity3d

I have this kind of code

List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("metadata","{ \"name\":" + salvataggio2.Substring(0, salvataggio2.Length - 5) + "-to-google-drive.json" + ", \"parents\":['" + entries.Files[0].Id + "'] }","application/json"));
formData.Add(new MultipartFormDataSection("file", Application.persistentDataPath + "/Saves/" + salvataggio2, "application/json"));
//formData.Add(new MultipartFormFileSection(salvataggio2.Substring(0, salvataggio2.Length - 5) + "-to-google-drive.json", Application.persistentDataPath + "/Saves/" + salvataggio2));
//string jsonMetadata = "--foo_bar_baz" + System.Environment.NewLine + " Content-Type: application/json; charset=UTF-8 { \"name\":" + salvataggio2.Substring(0, salvataggio2.Length - 5) + "-to-google-drive.json" + ", \"parents\":['" + entries.Files[0].Id + "'] }" + System.Environment.NewLine + "--foo_bar_baz" + System.Environment.NewLine + "Content-Type: application/json; charset=UTF-8" + File.ReadAllText(Application.persistentDataPath + "/Saves/" + salvataggio2) + System.Environment.NewLine + "--foo_bar_baz--" + System.Environment.NewLine;
//byte[] bytes = Encoding.UTF8.GetBytes(jsonMetadata);
using (UnityWebRequest www = UnityWebRequest.Post("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart", formData)) {
//var upload = new UploadHandlerRaw(bytes);
//www.uploadHandler = upload;
www.SetRequestHeader("Authorization", "Bearer " + response.Access_token);
//www.SetRequestHeader("Content-Type", "multipart/related; boundary=foo_bar_baz");

yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) {
    Debug.Log(www.downloadHandler.text);
    this.gameObject.SetActive(false);
} else {
    Debug.Log(www.downloadHandler.text);
}
}

Like you can see I need to upload a json file to google drive. I already got the fileId of the parent folder. Not sure what I do wrong but I got multiple errors. like

"code": 400, "message": "Parse Error" (for the code not commented right now), malformed multipart body if I try to use the MultipartFormFileSection part instead of the MultipartFormDataSection file part, missing end boundaries if I try to use the jsonMetadata with the "Content-Type", "multipart/related; boundary=foo_bar_baz".

How can I solve this problem?

EDIT. I tried to make Log of my current jsonMetadata variable (the one with everything) corrected some things and I got this

--foo_bar_baz
Content-Disposition: form-data; name="metadata"
Content-Type: application/json; charset=UTF-8

{ "name":"Autosave - Lief-to-google-drive.json", "parents":["1N7pYSBW-eI-sMcS0KF4cjd9IuTYVTani"] }
--foo_bar_baz
Content-Disposition: form-data; name="file"
Content-Type: application/json; charset=UTF-8

{"nickname":"Lief","sex":false,"startingPoint":[0.0,0.0,-5.0],"startingRotation":[0.0,0.0,0.0],"startingCameraPoint":[0.0,0.0,0.0],"startingCameraRotation":[0.0,0.0,0.0],"npcRep":[{"dialogNumber":"00001","rep":0,"side":"default"}],"sideRep":[{"side":"default","rep":0},{"side":"demo","rep":-100}]}
--foo_bar_baz--

I don't really undestand what I need to change because I still get "Missing end boundary in multipart body."

--foo_bar_baz-- should be the end

my code part looks like this now

string jsonMetadata = "--foo_bar_baz" + System.Environment.NewLine 
            + "Content-Disposition: form-data; name=\"metadata\"" + System.Environment.NewLine 
            + "Content-Type: application/json; charset=UTF-8" + System.Environment.NewLine + System.Environment.NewLine
            + "{ \"name\":\"" + salvataggio2.Substring(0, salvataggio2.Length - 5) + "-to-google-drive.json\"" + ", \"parents\":[\"" + entries.Files[0].Id + "\"] }" + System.Environment.NewLine 
            + "--foo_bar_baz" + System.Environment.NewLine
            + "Content-Disposition: form-data; name=\"file\"" + System.Environment.NewLine
            + "Content-Type: application/json; charset=UTF-8" + System.Environment.NewLine + System.Environment.NewLine
            + File.ReadAllText(Application.persistentDataPath + "/Saves/" + salvataggio2) + System.Environment.NewLine 
            + "--foo_bar_baz--" + System.Environment.NewLine;

Ok I was finally able to solve this problem (what I can say it is that I am not right now sure how it works, but I can say for sure that I needed to create Boundaries with Unity api)

        List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
        formData.Add(new MultipartFormDataSection("metadata", "{ \"name\":\"" + salvataggio2.Substring(0, salvataggio2.Length - 5) + "-to-google-drive.json\"" + ", \"parents\":[\"" + entries.Files[0].Id + "\"] }", "application/json"));
        formData.Add(new MultipartFormDataSection("file", File.ReadAllText(Application.persistentDataPath + "/Saves/" + salvataggio2), "application/json"));
        byte[] boundary = UnityWebRequest.GenerateBoundary();
        byte[] formSections = UnityWebRequest.SerializeFormSections(formData, boundary);
        byte[] terminate = Encoding.UTF8.GetBytes(String.Concat("\r\n--", Encoding.UTF8.GetString(boundary), "--"));
        byte[] body = new byte[formSections.Length + terminate.Length];
        Buffer.BlockCopy(formSections, 0, body, 0, formSections.Length);
        Buffer.BlockCopy(terminate, 0, body, formSections.Length, terminate.Length);
        string contentType = String.Concat("multipart/related; boundary=", Encoding.UTF8.GetString(boundary));

        using (UnityWebRequest www = UnityWebRequest.Post("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart", "")) {
            var upload = new UploadHandlerRaw(body);
            www.uploadHandler = upload;
            www.SetRequestHeader("Authorization", "Bearer " + response.Access_token);
            www.SetRequestHeader("Content-Type", contentType);

            yield return www.SendWebRequest();
            if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) {
                Debug.Log(www.downloadHandler.text);
                this.gameObject.SetActive(false);
            } else {
                Debug.Log(www.downloadHandler.text);
            }
        }

Like you can see after the first 2 Add to the formData (same as before) it create a random boundary, it serialize the form and the boundary, it create a termination, it fuse everything, and it create a compatible content Type. After that I just create the usual Unity Post (with UploadHandler for array of bytes in the body) and it's done.

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