cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
Want to learn some quick and useful tips to make your day easier? Check out how Calvin uses Replay to get feedback from other teams at Dropbox here.

Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

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

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

dwgabriel
Explorer | Level 3

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());
6 Replies 6

Greg-DB
Dropbox 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
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
Dropbox 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.

dwgabriel
Explorer | Level 3

The ERR_INVALID_HANDLE comes from here, when you mouse over the Status column of the request. 

dwgabriel_0-1617667872250.png

I'm currently using Google Chrome - Version 89.0.4389.114 (Official Build) (64-bit)

 

Thanks Greg! I'll go fix that right away. 

However, would the incorrect session_id header explain the Start session failing as well?

 

Greg-DB
Dropbox Staff

I see, thanks for clarifying. No, that wouldn't explain /start failing, since /start itself returns the session ID to begin with. I happened to be testing in Firefox, where the /start call did work successfully for me (and still does). 

 

Trying in Chrome now though, I can reproduce this issue. I'm not sure exactly why this is failing in Chrome but not Firefox, but as this is apparently due to some different in how Chrome itself handles this, as opposed to the Dropbox API itself, I may not be able to offer much help.

 

I notice that the call to /2/files/upload (for smaller files) does work in Chrome though. As a next step in debugging this, I recommend looking into what the difference is in your implementation for these different calls. It's difficult to see exactly what there is in the code on my side since it's minified, but it looks like you're doing a "return fetch..." for /2/files/upload, but don't have the "return" for /2/files/upload_session/start. Likewise, you seem to be manually specifying "Content-Length" for /2/files/upload_session/start but not for /2/files/upload. 

dwgabriel
Explorer | Level 3

Hey @Greg-DB , thanks for the insight, I'll give FireFox a try as well. 

As for the inconsistencies on my the two different fetches, I'm just desperate right now so I'm adding and removing parts of the fetch to see if it makes any difference. Since it threw a TypeError, I thought perhaps it had something to do with my syntax. As in my original post, I've tried to keep the two fetches as consistent as possible but still nothing unfortunately.

 

Thank you so much for taking the time to check this out, @Greg-DB . Greatly appreciate it!

Need more support?
Who's talking

Top contributors to this post

  • User avatar
    dwgabriel Explorer | Level 3
  • User avatar
    Greg-DB Dropbox Staff
What do Dropbox user levels mean?