无法使用 pre-signed URL 播放上传到 AWS S3 的 mp4 视频

Unable to play mp4 video uploaded to AWS S3 using pre-signed URL

我正在使用 pre-signed URL 将 mp4 视频上传到 AWS S3,上传成功,但是当我尝试从 S3 下载视频并在媒体播放器(VLC 或 quickTime),无法播放!

生成的 pre-signed URL 与 mp3 一起工作正常,但与上述相同的问题也发生在 WAVFLAC 上。

代码生成 pre-signed url:

public String getPreSignedS3Url( final String userId, final String fileName )
    {
        Date expiration = new Date();
        long expTimeMillis = expiration.getTime();
        expTimeMillis += urlExpiry;
        expiration.setTime(expTimeMillis);

        String objectKey = StringUtils.getObjectKey( userId, fileName );

        GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(
                recordingBucketName, objectKey)
                .withMethod(HttpMethod.PUT)
                .withExpiration(expiration);

        URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);

        return url.toString();

    }

在我从上面的方法得到 pre-signed URL 之后,我从 Postman 发出一个 HTTP PUT 请求,请求 body 中的 multipart/form-data 像这样:

-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F 'file=@/Users/john/Downloads/sampleDemo.mp4'

pre-signed url 看起来像这样:

https://meeting-recording.s3.eu-west-2.amazonaws.com/331902257/sampleDemo.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20190720T125751Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3599&X-Amz-Credential=AKIAZDSMLZ3VDKNXQUXH%2F20190720%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Signature=dfb8054f0738e07e925e9880e4a8e5ebba0a1bd3c84a3ec78913239f65221992

我尝试使用 generatePresignedUrlRequest.setContentType( "video/mp4" );getPreSignedS3Url() 方法中将内容类型设置为 mp4 并在 HTTP PUT 请求 header 中添加 Content-Type : "video/mp4" 但它没有工作但失败并出现错误 Signature doesn't match.

我将 S3 用作个人 back-up hard-drive,我希望使用 pre-signed URL 将视频和音频文件上传到 S3,下载它们以后可以玩了,下载了就玩不了

有人知道是什么原因造成的吗?

PUT 对 S3 的请求不支持 multipart/form-data。请求主体只需要包含二进制对象数据。如果您从 S3 下载现有文件并使用文本编辑器打开它,您会发现 S3 保留了文件内部的多部分表单结构,而不是将其解释为实际负载的包装器。

为了补充上面的答案(对于未来的读者),我使用如下的 formData() 来发送放置请求。将文件直接添加到负载对我有用。

不要这样做:

var bodyData = new FormData();
bodyData.append('file', video);

axios.put(res?.data?.uploadURL, bodyData, {

相反,这样做:

axios.put(res?.data?.uploadURL, video, {