spooky
spooky

Reputation: 421

Vimeo API file upload constantly returning 308 response

I've been stuck on this issue for over a week now, and have contacted Vimeo support but getting nowhere. Have read all the posts on here with similar issues but still no fix. The closest similar post is Vimeo API : streaming upload using HTTP PUT and blueimp's jQuery fileupload

..but i'm not using the jQuery fileupload plugin so that option doesn't apply (I'm using jQuery.ajax.

Anyway, i'm trying to upload videos using the HTTP PUT method (https://developer.vimeo.com/api/upload/videos#resumable-http-put-uploads)

I've generated an upload ticket as in step 1, and then sent a PUT request to the upload_link_secure as in step 2. Here is the request..

Request URL:https://1511923893.cloud.vimeo.com/upload?ticket_id=9b867d91d7e7f83bb31f0690b6331ac0&video_file_id=522193134&signature=89c47a9b3bfc4a0ece830b75d1845e86&v6=1

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Connection:keep-alive
Content-Length:10498886
Content-Type:video/mp4
Host:1511923893.cloud.vimeo.com
Origin:http://www.talentgapp.local
Referer:http://www.talentgapp.local/
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36

And the response..

Request URL:https://1511923893.cloud.vimeo.com/upload?ticket_id=9b867d91d7e7f83bb31f0690b6331ac0&video_file_id=522193134&signature=89c47a9b3bfc4a0ece830b75d1845e86&v6=1
Request Method:PUT
Status Code:200 OK
Remote Address:54.78.176.185:443

Response Headers

Access-Control-Allow-Headers:Content-Type, Content-Range,  X-Requested-With
Access-Control-Allow-Methods:POST, PUT, GET, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Range
Connection:close
Content-Length:0
Content-Type:text/plain
Date:Thu, 28 Apr 2016 11:39:53 GMT
Server:Vimeo/1.0
Timing-Allow-Origin:*
X-Backend-Server:kopiluwak
X-Requested-With:XMLHttpRequest

So far so good - the video even appears in my Vimeo account (but is in "uploading" status and never completes)

So, as recommended by the Vimeo docs, I then attempt to verify the upload as in step 3 (supplying the same request parameters as before, with the exception of the file data, and with the addition of the Content-Range: bytes */* header:

Request:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Connection:keep-alive
Content-Length:0
Content-Range:bytes */*
Content-Type:video/mp4
Host:1511923893.cloud.vimeo.com
Origin:http://www.talentgapp.local
Referer:http://www.talentgapp.local/
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36

And the response...

Request URL:https://1511923893.cloud.vimeo.com/upload?ticket_id=9b867d91d7e7f83bb31f0690b6331ac0&video_file_id=522193134&signature=89c47a9b3bfc4a0ece830b75d1845e86&v6=1
Request Method:PUT
Status Code:308 Resume Incomplete
Remote Address:54.78.176.185:443

Response headers..

Access-Control-Allow-Headers:Content-Type, Content-Range,  X-Requested-With
Access-Control-Allow-Methods:POST, PUT, GET, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Range
Connection:close
Content-Length:0
Content-Type:text/plain
Date:Thu, 28 Apr 2016 11:39:53 GMT
Range:bytes=0-10498886
Server:Vimeo/1.0
Timing-Allow-Origin:*
X-Backend-Server:kopiluwak
X-Requested-With:XMLHttpRequest

As you can see I am getting Range:bytes=0-10498886 in the 308 response. I repeat this request several times but the Range header is always bytes=0-10498886 and I never get a 200 response to confirm the upload has completed.

As such, if I perform the DELETE request as described in step 4 i get error 500: Invalid state.

Anybody have any ideas?

Upvotes: 1

Views: 1223

Answers (2)

spooky
spooky

Reputation: 421

Finally i have this working now.

Credit to @razethestray for leading me in the right direction.

Turns out there is no need to append the file(s) to a FormData object before sending via XHR.

Simply send the file as it is, and it's working..

e.g.

$.ajax({
            url : uploadUri,
            method : 'PUT',
            contentType : false,
            crossDomain : true,
            headers : {
                'Content-Type' : file.type,
                'Content-Range': "bytes " + 0 + "-" + (file.size) + "/" + file.size
            },
            processData : false,
            data : files[0]  // Not a FormData object
        })
        .done(function(){
            // complete upload
        })

Also, I learnt that the verification requests will NEVER return a status 200 - which is what Vimeo's documentation mislead me to believe.

The verification request will always return 308 with the Range:bytes=0-10498886 header, the first part of which will never go above zero. It is the 2nd part (10498886) that you should check to see if it matches the size of the original file. If it does, then complete the upload. If you perform the verification request while the file is uploading, you will notice that the 2nd part of the range will increment until the file has fully uploaded.

Hope this helps others.

Upvotes: 2

razethestray
razethestray

Reputation: 676

I was also having this problem, but managed to solve it, for my use case at least.

You don't state in what format you were sending the data, but in my case I was sending a FormData object. I changed this to send a raw byte array instead and it started working.

Previously (Not Working):

function getVideoFormData($fileUpload) {
    var formData = new FormData();
    formData.append($fileUpload.files[0].name, $fileUpload.files[0]);
    return formData;
}

$.ajax({
    type: "PUT",
    /*Other relevant options...*/
    data: getVideoFormData($"#my-video-id");
});

Now (Working):

function getVideoFormData($fileUpload) {    
    var promise = $.Deferred();

    var reader = new FileReader();
    reader.onload = function () {
        var bytes = this.result;
        promise.resolve(bytes); 
    };
    reader.readAsArrayBuffer($fileUpload.files[0]);

    return promise;
}

getVideoFormData($"#my-video-id").done(function(bytes){
    $.ajax({
        type: "PUT",
        /*Other relevant options...*/
        data: bytes;
    });
});

Note that readAsArrayBuffer does not instantly return the array buffer. Instead load the result in the reader.onload handler. Since this didn't happen synchronously, I had to add a jQuery Deferred object.

I tried using reader.readAsBinaryString but this had the same result as the FormData approach. reader.readAsArrayBuffer method is working for me now however in Chrome/FF/IE11.

Note that the result of the verify step is still a 308, but the video is correctly uploaded and the DELETE step now returns 200.

Upvotes: 1

Related Questions