Learn how to make the most out of the Dropbox Community here 💙. 

Forum Discussion

dwgabriel's avatar
dwgabriel
Explorer | Level 3
4 years ago

Dropbox UploadSession Start/Append/Finish with Fetch - TypeError:Failed to fetch

Hi guys, I'm using Fetch with Dropbox for file uploads on my website and it works fine for uploads <150 mb

(https://content.dropboxapi.com/2/files/upload)

 

However, when I attempt upload >150 mb files using UploadSessionStart/Append/Finish, it throws a 'TypeError : Failed to fetch' in the console. On the Network tab, it just says (failed) net::ERR_INVALID_HANDLE. I can't seem to figure out what's wrong. I'm doing from my Wix website and followed this example - https://github.com/dropbox/dropbox-sdk-js/blob/master/examples/javascript/upload/index.html 

 

I didn't use the upload functions from the Dropbox SDK as shown in the example because Wix can't seem to import the module correctly so I had to resolve to directly fetching to Dbx's upload URL instead. I've pasted my code for fetching UploadSession Start/Append/Finish below. Please let me know where I messed up or point me to a Fetch example of this, if any. 

 

 

const maxBlob = 8 * 1000 * 1000;
                var workItems = [];
                var offset = 0;
                var sessionID;

                // Slice the file into chunks for upload session
                while (offset < file.size) {
                    var chunkSize = Math.min(maxBlob, file.size - offset);
                    workItems.push(file.slice(offset, offset + chunkSize));
                    offset += chunkSize;
                }

                const task = workItems.reduce((acc, blob, idx, items) => {
                    if (idx == 0) {
                      // Start multipart upload of file
                        return acc.then(function() {
                            return fetch(dbxURL_start, {
                                        "method""post",
                                        "headers": {
                                        "Authorization" : "Bearer *ACCESS_TOKEN*",
                                        "Content-Type""application/octet-stream",
                                        "Dropbox-API-Arg""{\"close\":false}"
                                        },
                                    "body": blob
                            })
                            .then((response) => {
                                sessionID = response.session_id;
                            })                                      
                            .catch(err => console.log("[ERROR] UPLOAD_SESSION_START : " + err));
                        })
                  } else if (idx < items.length-1) {
                      // Append part to the upload session
                      return acc.then(function(sessionID) {
 
                          return fetch(dbxURL_append, {
                                        "method""post",
                                        "headers": {
                                        "Authorization" : "Bearer *ACCESS_TOKEN*",
                                        "Content-Type""application/octet-stream",
                                        "Dropbox-API-Arg""{\"cursor\": {\"session_id\": \"" + sessionID + "\",\"offset\":\"" + (idx * maxBlob) + "\"},\"close\":false}"
                                        },
                                    "body": blob
                            })
                            .then(() => sessionID)
                            .catch(err => console.log("[ERROR] UPLOAD_SESSION_APPEND : " + err));
                      })
                  } else {
                      // Last chunk of data, close upload session
                      return acc.then(function(sessionID) {

                          return fetch(dbxURL_finish, {
                                        "method""post",
                                        "headers": {
                                        "Authorization" : "Bearer *ACCESS_TOKEN*",
                                        "Content-Type""application/octet-stream",
                                        "Dropbox-API-Arg""{\"cursor\": {\"session_id\": \"" + sessionID + "\",\"offset\":\"" + (file.size - blob.size) + "\"},\"commit\": {\"path\":\"/render/" + filename + "\",\"mode\":{\".tag\":\"add\"}}, \"close\":true}"
                                        },
                                    "body": blob
                            })
                            .then((httpResponse) => {
                                if (httpResponse.ok){
                                    console.log("HTTP RES : OK")
                                    return httpResponse.ok
                                } else {
                                    console.log("HTTP RES : NOT OK")
                                    return !httpResponse.ok
                                }                                   
                            })
                            .catch(err => console.log("[ERROR] UPLOAD_SESSION_FINISH : " + err));
                      })
                  }
              }, Promise.resolve());
  • Greg-DB's avatar
    Greg-DB
    Icon for Dropbox Staff rankDropbox Staff

    I'm not sure off hand what that error would indicate. (It's not an error from the Dropbox API itself.) Do you have a live sample page where I can plug in my own access token and test this out so I can take a look?

    • dwgabriel's avatar
      dwgabriel
      Explorer | Level 3

      GREG! Thank you so much for answering.

       

      Yes, just created a live page for you to test. 

      https://www.nebula.my/greg-db 

       

      It uses the exact same code I showed in my post, just substituted my access token with the input. 

      • Greg-DB's avatar
        Greg-DB
        Icon for Dropbox Staff rankDropbox Staff

        Thanks! I just tried this out but I don't see the "ERR_INVALID_HANDLE" error you mentioned, when attempting to upload a file larger than 150 MB. What browser/version are you using?

         

        I do notice that you don't seem to be sending the session ID up properly on the /append_v2 calls. The parameters being sent look like:

        {"cursor": {"session_id": "undefined","offset":"8000000"},"close":false}

         

        So, it seems you have a bug when you get or set the session ID. You'll need to make sure you supply that session ID value (as returned by /start), not undefined.