Score:0

Dropzone: How to upload video to S3 using presigned URL and play it in browser? Doesn't quite work

gb flag

I have Dropzone set up to allow users to upload videos directly to an S3 presigned URL using the PUT method. Here is my Dropzone script:

var presign = "#";
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone("#dropzone", {
  url: presign,
  method: "PUT",
  dictDefaultMessage: "Click Here upload video.",
  maxFilesize: 10000, // MB
  maxFiles: 100,
  addRemoveLinks: true,
  headers: {
    "x-amz-acl": "public-read",
    "Content-Type": "video/mp4"
  },
  init: function() {
    this.on("addedfile", function(file) {
      fileupload_flag = 1;}
    );
    this.on("complete", function (file) {
      fileupload_flag = 0;
    });
    this.on("processing", function (file) {
      this.options.url = presign;
    });
  },
  accept: function(file, done) {
    console.log(file['type']);
    if (file && file['type'].split('/')[0] === 'video') {
      var xhr = new XMLHttpRequest();
      xhr.open("POST", "https://www.example.com/test-getpresign.php");
      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      xhr.send("mime="+JSON.stringify(file['type']));
      xhr.onreadystatechange = function() {
        if (this.readyState == 4) {
          if(this.status == 200 && this.responseText != '') {
            result = JSON.parse(this.responseText);
            presign = result.url;
            done();
          }
        }
      }
    }
    else { 
      done("Please select only supported picture files."); 
    }
  },
  success: function(file, response){
    this.removeFile(file);
  }     
});

In the "accept" function, which fires before the actual upload, I run an xhr call to a PHP script on my site that generates presigned URLs for my S3, and then returns them to Dropzone and updates the PUT url for where to send the file to. The PHP code for creating the presigned S3 URL is as follows:

$cdnvideo = new Aws\S3\S3Client([
    'version'     => '2006-03-01',
    'region'      => REGION,
    'endpoint'    => HOST,
        'credentials' => [
        'key'      => AWS_KEY,
        'secret'   => AWS_SECRET_KEY,
    ]
]);

$key = 'video.mp4';
$cmd = $cdnvideo->getCommand('PutObject', [
  'Bucket' => 'bucketname',
  'Key'    => $key,
  'ContentType' => 'video/mp4'
]);
$request = $cdnvideo->createPresignedRequest($cmd, '+720 minutes');
$url = (string) $request->getUri();

In an example, I attempt to upload a 30-second video 1.5MB in size. It seems that Dropzone sends something to S3. In the bucket list, I am seeing the correct filename at S3, including the correct file size (1.5 MB) and content type "video/mp4'. But when I go to the object URL in my browser to view the actual video, it's a video with 0 seconds, with a 206 HTTP code and apparently 1.1MB downloaded loaded over the network. The video is broken and doesn't load.

Here is the Request in chrome's developer tools:

Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 1570227
Content-Type: video/mp4
Host: *****
Origin: https://www.example.com
Referer: https://www.example.com/
Sec-Ch-Ua: "Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36
X-Amz-Acl: public-read
X-Requested-With: XMLHttpRequest

PAYLOAD:

X-Amz-Content-Sha256: UNSIGNED-PAYLOAD
X-Amz-Algorithm: AWS4-HMAC-SHA256
X-Amz-Credential: A86SB6NKA1KWC4EF8Z25%2F20230821%2Fus-east-1%2Fs3%2Faws4_request
X-Amz-Date: 20230821T015024Z
X-Amz-SignedHeaders: host
X-Amz-Expires: 43200
X-Amz-Signature: 2f00a4eff448fc0ba889ed83e207a87d6df42cd0d7b1252f9a68b1056dec8b09
------WebKitFormBoundaryfApLoQv4mFg4SHAw
Content-Disposition: form-data; name="file"; filename="video.mp4"
Content-Type: video/mp4


------WebKitFormBoundaryfApLoQv4mFg4SHAw--

I'm not seeing a Response, not sure if there is supposed to be or not.

What am I doing wrong here? It seems like this is a problem with Dropzone. Although maybe I'm creating the presigned URL incorrectly? My goal is to simply have Dropzone PUT the user's video into S3 and make that object "public-read", so it can immediately play in the browser.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.