Dropzone:如何使用预签名 URL 将视频上传到 S3 并在浏览器中播放?不太管用

Dropzone:如何使用预签名 URL 将视频上传到 S3 并在浏览器中播放?不太管用

我已设置 Dropzone,以允许用户使用 PUT 方法将视频直接上传到 S3 预签名 URL。这是我的 Dropzone 脚本:

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);
  }     
});

在实际上传之前触发的“accept”函数中,我运行 xhr 调用我网站上的 PHP 脚本,该脚本为我的 S3 生成预​​签名 URL,然后将它们返回到 Dropzone 并更新 PUT URL 以指定将文件发送到的位置。用于创建预签名 S3 URL 的 PHP 代码如下:

$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();

例如,我尝试上传一个 30 秒、大小为 1.5MB 的视频。看来 Dropzone 向 S3 发送了一些东西。在存储桶列表中,我看到了 S3 上的正确文件名,包括正确的文件大小(1.5 MB)和内容类型“video/mp4”。但是当我在浏览器中转到对象 URL 来查看实际视频时,它是一个时长为 0 秒的视频,HTTP 代码为 206,显然通过网络下载了 1.1MB。视频已损坏,无法加载。

以下是chrome开发者工具中的请求:

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

有效载荷:

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--

我没有看到回复,不确定是否应该有。

我在这里做错了什么?这似乎是 Dropzone 的问题。虽然我可能错误地创建了预签名 URL?我的目标是让 Dropzone 将用户的视频放入 S3 并使该对象成为“公开可读”,这样它就可以立即在浏览器中播放。

相关内容