Python3 + jQuery-File-Upload直接上传s3 |方法不允许405

时间:2018-05-23 13:49:43

标签: python amazon-s3 flask jquery-file-upload

我正在使用Python 3 + Flask将视频文件直接上传到我的S3存储空间,但我得到Method not allowed 405

此外,上传必须在客户端工作,因为视频文件没有大小限制并且会很大。这会导致服务器超时。

这是我的CORS&铲斗政策:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

Bucket Policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::mybucket/*"
        }
    ]
}

在服务器端,我用它来签署请求:

# Sign request for direct file upload through client for video
@app.route('/sign_s3/<path:file_name_data>/<path:file_type_data>/<up_type>', methods=["GET", "POST"])
@login_required
@check_confirmed
def sign_s3(file_name_data, file_type_data, up_type):
    if "localhost" in request.url_root:
        if up_type == "profile_vid":
            file_name = str(current_user.id) + get_random_code(5) + "local-profil-video." + file_name_data.split(".")[-1]
        else:
            file_name = str(current_user.id) + str(randint(1,100)) + "local-post-video-temp." + file_name_data.split(".")[-1]
    else:
        if up_type == "profile_vid":
            file_name = str(current_user.id) + get_random_code(5) + "-profil-video." + file_name_data.split(".")[-1]
        else:
            file_name = str(current_user.id) + str(randint(1,100)) + "-post-video-temp." + file_name_data.split(".")[-1]

    file_type = file_type_data

    session = boto3.Session(
        aws_access_key_id=app.config['MY_AWS_ID'],
        aws_secret_access_key=app.config['MY_AWS_SECRET'],
        region_name='eu-central-1'
    )

    presigned_post = s3.generate_presigned_post(
    Bucket = 'mybucket',
    Key = 'videos/' + file_name,
    Fields = {"acl": "public-read", "Content-Type": file_type},
    Conditions = [
      {"acl": "public-read"},
      {"Content-Type": file_type}
    ],
    ExpiresIn = 3600
    )

    if up_type == "profile_vid":
        if current_user.profile_video != None:
            delete_file_from_aws("videos/", current_user.profile_video)
        setattr(current_user, "profile_video", file_name)
    else:
        print ('post video has been uploaded, no need to delete or set here')

    db_session.commit()

    return json.dumps({'data': presigned_post, 'url': 'https://s3.eu-central-1.amazonaws.com/mybucket/' + 'videos/' + file_name, 'created_file_name' : file_name})

这里是客户端Jquery File Uploade代码:

/************************
 * Upload for video
 *************************/
$('#NEW_fileupload_video').fileupload({
    autoUpload: false,
    maxNumberOfFiles: 1,
    disableVideoPreview: false,
    // new
    forceIframeTransport: true, // VERY IMPORTANT.  you will get 405 Method Not Allowed if you don't add this.
    singleFileUploads: true, //default anyway
    // end new
    maxFileSize: 9999999000
}).on('fileuploadadd', function (e, data) {
    if ($('#NEW_fileupload_video_files div')[0]) {
        $('#NEW_fileupload_video_files div').remove();
    }   

    var files = data.files || [];
    var nextInQueue = files[0]; //this is a queue, not a list
    if (!nextInQueue) return;

    var fileData = {name: nextInQueue.name, mime: nextInQueue.type, size: nextInQueue.size};

    $.ajax({
        url: "/sign_s3/" + data.files[0].name + "/" + data.files[0].type + "/" + 'profile_vid',
        type: 'POST',
        dataType: 'json',
        // I am giving the data through the URL, probably a bad idea
        data: {'file': fileData},
        async: false,
        success: function(res) {
            var response_json_data = res;

            $('input[name="key"]').val(response_json_data.data.fields['key']);
            $('input[name="AWSAccessKeyId"]').val(response_json_data.data.fields['x-amz-credential']);
            $('input[name="policy"]').val(response_json_data.data.fields['policy']);
            $('input[name="signature"]').val(response_json_data.data.fields['x-amz-signature']);
            $('input[name="acl"]').val( response_json_data.data.fields['acl']);
            $('input[name="success_action_status"]').val("200");
            $('input[name="Content-Type"]').val(nextInQueue.type);
            //$('#direct_s3_profile_video_form').attr('action', response_json_data.url);
            $('#direct_s3_profile_video_form').attr('action', 'https://mybucket.s3.amazonaws.com/videos/' + response_json_data.created_file_name);
            data.submit();
        }
    }); 
}).on('fileuploadprocessalways', function (e, data) {
    console.log("NEW always");
    var index = data.index,
        file = data.files[index],
        node = $(data.context.children()[index]);
    if (file.preview) {
        node
            .prepend('<br>')
            .prepend(file.preview);
    }
    if (file.error) {
        node
            .append('<br>')
            .append($('<span class="text-danger"/>').text(file.error));
        console.log("here", file.error);
    }
    if (index + 1 === data.files.length) {
        data.context.find('button')
            .text('Upload')
            .prop('disabled', !!data.files.error);
        }
}).on('fileuploadprogressall', function (e, data) {
    var progress = parseInt(data.loaded / data.total * 100, 10);
    $('#NEW_progress_fileupload_video .progress-bar').css(
        'width',
        progress + '%'
    );
}).on('fileuploaddone', function (e, data) {
    console.log("done client side video up profile");
}).on('fileuploadfail', function (e, data) {
    console.log("fail", e, data);
})

这是HTML:

<form id="direct_s3_profile_video_form" class="form-horizontal" role="form" method="POST" enctype="multipart/form-data">
 <input id="NEW_fileupload_video" type="file" name="NEW_fileupload_video_files[]" accept="video/*">
 <input type="hidden" name="key">
 <input type="hidden" name="AWSAccessKeyId">
 <input type="hidden" name="policy">
 <input type="hidden" name="signature">
 <input type="hidden" name="acl">
 <input type="hidden" name="success_action_status">
 <input type="hidden" name="Content-Type">
 <div id="NEW_progress_fileupload_video" class="progress">
     <div class="progress-bar progress-bar-success"></div>
 </div>
 <div id="NEW_fileupload_video_files" class="files"></div>
 <button type="submit"> Upload </button>
</form>

我知道很多代码。我非常接近理解这一切是如何运作的。我想我错过了一些简单的东西。欢迎任何想法!我真的很感激。

修改

以下是DEV控制台的标题:

GENERAL:

Request URL: https://s3.eu-central-1.amazonaws.com/mybucket/videos/3rBHwNlocal-profil-video.mp4
Request Method: POST
Status Code: 405 Method Not Allowed
Remote Address: 52.219.74.48:443
Referrer Policy: no-referrer-when-downgrade

响应标题:

Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Origin: *
Allow: HEAD, DELETE, GET, PUT
Connection: close
Content-Type: application/xml
Date: Wed, 23 May 2018 15:18:49 GMT
Server: AmazonS3
Transfer-Encoding: chunked
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
x-amz-id-2: SOME DATA
x-amz-request-id: MY ID

请求标题:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 1057282
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5gUAipNLOHxSqN8F
Host: s3.eu-central-1.amazonaws.com
Origin: http://localhost:5000
Referer: http://localhost:5000/profile
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36

0 个答案:

没有答案