#2251·dropzone

Dropzone: How to upload video to S3 using presigned URL and play it in browser? Almost works, but not quite.

Author: peppiesCreated Aug 21, 2023Updated Aug 6, 2026

Dropzone version: 5.9.3

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.