如何将InMemoryUploadedFile上传到我的S3 Bucket?

时间:2018-03-17 04:20:11

标签: javascript python jquery django amazon-s3

我有一个简单的上传表单,其中包含一个FileField的图片:

def post(request):    
    if request.user.is_authenticated():
        form_post = PostForm(request.POST or None, request.FILES or None)
        if form_post.is_valid():
            instance = form_post.save(commit=False)
            instance.user = request.user

            instance.save()

            return HttpResponseRedirect('/home/')
        else:
            form_post = PostForm()

        context = {
            'form_post': form_post,
        }
        return render(request, 'post/post.html', context)
    else:
        return HttpResponseRedirect("/accounts/signup/")

当用户将图像添加到表单时,它会触发此JS函数:

$('input#id_image').on('change', function(e) {...} 

可以预览图像。这就是我希望将图像上传到我的媒体文件夹目录(我正在使用S3存储)的地方。默认情况下,用户提交表单时会上传图片,但我希望在$('input#id_image').on('change'触发后立即上传图片。

到目前为止我所做的是在我的视图中以InMemoryUploadedFile格式检索图像:

$('input#id_image').on('change', function(e) {
var formData = new FormData();

formData.append('image', $('input[type=file]')[0].files[0]);
formData.append('csrfmiddlewaretoken', $("input[name='csrfmiddlewaretoken']").val());

$.ajax({
    url: '/upload_image/',
    data: formData,
    type: 'POST',
    contentType: false,
    processData: false, 
    ...
});

^发送到视图:

def upload_image(request):
    if request.is_ajax():
        img = request.FILES.get('image')
        print(img) #successfully prints the filename

但是我将这个InMemoryUploadedFile上传到我的S3存储桶时,我会陷入下一步的困境。有什么建议吗?

修改

img = request.FILES.get('image')
print(img)  # successfully prints the filename

s3_connection = boto.connect_s3(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, host="us-east-1")
bucket = s3_connection.get_bucket('my-bucket', validate=False)
key = Key(bucket, img.name)
key.send_file(img) #this line fires the error
return HttpResponse('upload ok')

key.send_file(img)会返回此错误:

socket.gaierror: [Errno 8] nodename nor servname provided, or not known

Traceback (most recent call last):
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/zorgan/Desktop/project/site/draft1/views.py", line 201, in upload_image
    key.send_file(img)
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/boto/s3/key.py", line 762, in send_file
    chunked_transfer=chunked_transfer, size=size)
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/boto/s3/key.py", line 963, in _send_file_internal
    query_args=query_args
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/boto/s3/connection.py", line 671, in make_request
    retry_handler=retry_handler
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/boto/connection.py", line 1071, in make_request
    retry_handler=retry_handler)
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/boto/connection.py", line 1030, in _mexe
    raise ex
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/boto/connection.py", line 940, in _mexe
    request.body, request.headers)
  File "/Users/zorgan/Desktop/app/lib/python3.5/site-packages/boto/s3/key.py", line 803, in sender
    http_conn.endheaders()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1102, in endheaders
    self._send_output(message_body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 934, in _send_output
    self.send(msg)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 877, in send
    self.connect()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1252, in connect
    super().connect()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 849, in connect
    (self.host,self.port), self.timeout, self.source_address)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/socket.py", line 693, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/socket.py", line 732, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

2 个答案:

答案 0 :(得分:2)

boto工作有问题,但我已升级到boto3,现在工作正常。

以下是代码:

img = request.FILES.get('image')
session = boto3.Session(
    aws_access_key_id=AWS_ACCESS_KEY_ID,
    aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
)
s3 = session.resource('s3')

s3.Bucket('my-bucket').put_object(Key='media/%s' % img.name, Body=img)
return HttpResponse()

这在AJAX调用期间成功将图像上传到我的存储桶。

答案 1 :(得分:1)

试试这个,

import boto
from boto.s3.key import Key
from django.http import HttpResponse


def upload_image(request):
    if request.is_ajax():
        img = request.FILES.get('image')
        print(img)  # successfully prints the filename

        s3_connection = boto.connect_s3("YOUR CREDENTIALS")
        bucket = s3_connection.get_bucket('your bucket name')
        key = Key(bucket, img.name)
        key.send_file(img.read())
        return HttpResponse('upload ok')


NB:我没试过,我发现了一个related answer here