boto3'str'对象没有属性'get

时间:2016-09-21 02:18:48

标签: python django heroku amazon-s3 boto3

我正在关注https://devcenter.heroku.com/articles/s3-upload-python的示例,用于将文件从客户端直接上传到s3并出现错误

views.api.sign_s3:

def sign_s3(request):

    S3_BUCKET = os.environ.get('S3_BUCKET')
    file_name = request.GET.get('file_name',False)
    file_type = request.GET.get('file_type',False)

    s3 = boto3.client('s3')

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

    return json.dumps({
        'data': presigned_post,
        'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name)
    })

settings.py:

os.environ['S3_BUCKET'] = 'mybucketname'
os.environ['AWS_ACCESS_KEY_ID'] = 'myaccesskey'
os.environ['AWS_SECRET_ACCESS_KEY'] = 'mysecretaccesskey'

html文件

<input id="file_input" name="video_files" type="file">
<!-- other html omitted -->

<script>
(function() {
    document.getElementById("file_input").onchange = function(){
        var files = document.getElementById("file_input").files;
        var file = files[0];
        if(!file){
            return alert("No file selected.");
        }
        $(files).each(function(i,file){
             getSignedRequest(file);
        });
   };
})();

function getSignedRequest(file){
    var xhr = new XMLHttpRequest();
    console.log(file);
    xhr.open("GET", "/api/sign_s3?file_name="+file.name+"&file_type="+file.type);
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
            if(xhr.status === 200){
                var response = JSON.parse(xhr.responseText);
                uploadFile(file, response.data, response.url);
            }else{
                alert("Could not get signed URL.");
            }
        }
   };
   xhr.send();
}

function uploadFile(file, s3Data, url){
    var xhr = new XMLHttpRequest();
    xhr.open("POST", s3Data.url);

    var postData = new FormData();
    for(key in s3Data.fields){
        postData.append(key, s3Data.fields[key]);
    }
    postData.append('file', file);

    xhr.onreadystatechange = function() {
        if(xhr.readyState === 4){
            if(xhr.status === 200 || xhr.status === 204){
                document.getElementById("preview").src = url;
                document.getElementById("avatar-url").value = url;
            }else{
                alert("Could not upload file.");
            }
       }
   };
   xhr.send(postData);
 }

</script>

回溯:

AttributeError at /api/sign_s3/
'str' object has no attribute 'get'
Request Method: GET
Request URL:    http://127.0.0.1:1337/api/sign_s3/?    file_name=jam13.mp4&file_type=video/mp4
Django Version: 1.8.5
Exception Type: AttributeError
Exception Value:    
'str' object has no attribute 'get'
Exception Location: c:\Python27\lib\site-packages\django\middleware\clickjacking.py in process_response, line 31
Python Executable:  c:\Python27\python.exe
Python Version: 2.7.3

...

c:\Python27\lib\site-packages\django\middleware\clickjacking.py in process_response
clickjacking protection techniques should be used if protection in those
browsers is required.
https://en.wikipedia.org/wiki/Clickjacking#Server_and_client
"""
def process_response(self, request, response):
    # Don't set it if it's already in the response
                if response.get('X-Frame-Options', None) is not None: ...
        return response
    # Don't set it if they used @xframe_options_exempt
    if getattr(response, 'xframe_options_exempt', False):
        return response

任何人都知道出了什么问题?

1 个答案:

答案 0 :(得分:0)

我认为您将视图返回给视图的方式会造成麻烦。

尝试这样的事情 -

import json
from django.http import HttpResponse, JsonResponse

def sign_s3(request):
   #Your View Code Here...

   #Finally The Response (Using JsonResponse)...
   json_object = {
    'data': presigned_post,
    'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name)
   }
   return JsonResponse(json_object)

   #Another Response Option (Using HttpResponse)
   data = {
    'data': presigned_post,
    'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name)
   }
   return HttpResponse(json.dumps(data), content_type = "application/json")