Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Cloud Storage upload request sometimes works, sometimes doesn't - make resumable?

A bit of a pickle here. I've got a Google Cloud Storage bucket set up, and a webpage that, probably about 60% of the time, DOES upload a file to the bucket. However, sometimes it doesn't and I don't really know why.

I'm trying this from a mobile handset so it could be the signal. As such, I guess one thing I need to think about is making it resumable (the files themselves aren't big - less than 2mb, but the service we're getting isn't great).

So, how could I make this into a resumable (rather than multipart) upload? And do you think this would solve the issue?

Code below:

            function insertObject(event) {
            try {
                var fileData = event.target.files[0];
            } 
            catch(e) {
                return;
            }
          var boundary = '-------314159265358979323846';
          var delimiter = "\r\n--" + boundary + "\r\n";
          var close_delim = "\r\n--" + boundary + "--";

            var reader = new FileReader();
            reader.readAsBinaryString(fileData);
            reader.onload = function(e) {
                var contentType = fileData.type || 'application/octet-stream';
                var metadata = {
                    'name': fileData.name,
                    'mimeType': contentType
                };

                var base64Data = btoa(reader.result);
                var multipartRequestBody =
                  delimiter +
                  'Content-Type: application/json\r\n\r\n' +
                  JSON.stringify(metadata) +
                  delimiter +
                  'Content-Type: ' + contentType + '\r\n' +
                  'Content-Transfer-Encoding: base64\r\n' +
                  '\r\n' +
                  base64Data +
                  close_delim;

                //Note: gapi.client.storage.objects.insert() can only insert
                //small objects (under 64k) so to support larger file sizes
                //we're using the generic HTTP request method gapi.client.request()
                var request = gapi.client.request({
                    'path': '/upload/storage/' + API_VERSION + '/b/' + BUCKET + '/o',
                    'method': 'POST',
                    'params': {'uploadType': 'multipart'},
                    'headers': {
                        'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
                    },
                    'body': multipartRequestBody});
                //Remove the current API result entry in the main-content div
                //listChildren = document.getElementById('main-content').childNodes;
                //if (listChildren.length > 1) {
                //    listChildren[1].parentNode.removeChild(listChildren[1]);
                //} 

                //look at http://stackoverflow.com/questions/30317797/uploading-additional-metadata-as-part-of-file-upload-request-to-google-cloud-sto

                try{
                    //Execute the insert object request
                    //document.getElementById("authorize-button").click();
                    executeRequest(request, 'insertObject');
                    //Store the name of the inserted object
                    document.getElementById("btnUpload").click();
                    object = fileData.name;
                }
                catch(e) {
                    alert('An error has occurred: ' + e.message);
                }
            }
        }

EDIT - just tried it from my PC and it's uploaded 17 files with no problems - normally it just starts dropping them straight away from the mobile handset. So I think it is a signal issue and making it resumable would do the job.

like image 344
Michael Bell Avatar asked Dec 28 '25 16:12

Michael Bell


1 Answers

Well, this is embarrassing.

I decided to check that the code was uploading the file correctly, and got rid of the

document.getElementById("btnUpload").click();
object = fileData.name;

in the final element of the code (the btnUpload does some C# stuff that I do need, but I don't need the object at all). I tried 20 pictures from my mobile handset and, when it would have usually only done about 12, it did all 20 - and a lot more effectively.

So I think the issue is the btnUpload.click that is taking control of the process away from the file transfer before it's finished. I've just got to find a way to incorporate that back into the code without interfering with things.

Github link

And just moved the btnUpload.click() from being within the insertobject to the executeRequest (just after where it calls the log). There just seems to be a small problem now, but not with the file upload. The btnUpload stuff gets called where it should, and the rest is simply sorting out the webpage.

Edit - as an aside, in order to cope with the request length being long (for files which are 4mb or more), I added this to the web.config (in the system.web):

<httpRuntime maxRequestLength="214748364"/>
like image 96
Michael Bell Avatar answered Dec 30 '25 04:12

Michael Bell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!