图片上传:iPhone客户端 - Django - S3

3

我有一个关于客户端上传(在这种情况下是iPhone应用程序)到S3的普遍问题。我正在使用Django在EC2实例上编写Web服务。以下方法是将文件上传到S3的最少要求,对于较小的文件(jpg或png < 1 MB),它非常有效:

def store_in_s3(filename, content):
    conn = S3Connection(settings.ACCESS_KEY, settings.PASS_KEY) # gets access key and pass key from settings.py
    bucket = conn.create_bucket('somebucket')
    k = Key(bucket) # create key on this bucket
    k.key = filename
    mime = mimetypes.guess_type(filename)[0]
    k.set_metadata('Content-Type', mime)
    k.set_contents_from_string(content)
    k.set_acl('public-read')

def uploadimage(request, name):
    if request.method == 'PUT':
        store_in_s3(name,request.raw_post_data)
        return HttpResponse("Uploading raw data to S3 ...")
    else:
        return HttpResponse("Upload not successful!")

我对这个完全陌生,所以我还不理解这里发生了什么。它是这样的情况吗:
  • Django接收文件并将其保存在我的EC2实例的内存中?
  • 我应该避免使用raw_post_data,而采用分块来避免内存问题吗?
  • 一旦Django接收到文件,它会将文件传递给store_in_s3函数吗?
  • 如何知道上传到S3是否成功?
总的来说,我想知道一行代码是否会在另一行代码之后执行。例如,当return HttpResponse("Uploading raw data to S3 ...")触发时,文件仍在上传中还是上传成功后?
感谢你的帮助。此外,我会感激任何涉及此主题的文档。我看了O'Reilly的Python & AWS Cookbook的章节,但因为它只有代码示例,所以并没有真正回答我的问题。
2个回答

1

Django会将小的上传文件存储在内存中。如果超过一定大小,它将把它存储在磁盘上的临时文件中。

是的,分块对于节省内存也是有帮助的:

for file_chunk in uploaded_file.chunks():
    saved_file.write(file_chunk)

所有这些操作都是同步的,因此Django将等待文件完全上传后再尝试将其存储在S3中。 S3也必须完成其上传才能返回,因此您可以确保它将通过Django上传并传输到S3,然后才会收到HttpResponse()。
Django的文件上传文档提供了大量有关如何处理各种上传情况的信息。

谢谢,非常有帮助。我刚查看了几篇其他的文章,似乎最好的解决方案是将客户端(iPhone)中的东西直接上传到S3。这样可以避免服务器端的繁琐操作,并且不会增加额外的流量(也就是说,不需要先将文件上传到EC2/Django,然后再上传到S3)。 - n.evermind
1
没错,你所说的唯一需要注意的是如果你对上传的图片进行任何处理。在我的业务中,每个图像都会在Django服务器上调整大小到不同的尺寸,然后上传到CDN。这只是一个例子,但也是你自己应用程序需要记住的事情。 - Jordan
我明白了。所以,如果我不在服务器上进行图像处理,那么就直接使用客户端->S3的方式。如果我需要进行一些处理,我会通过Django服务器进行。再次感谢您,这真的很有帮助。 - n.evermind
1
没错。如果你想绕过这个问题,你也可以在客户端上传到S3之后从某种服务中进行后处理。但这会更加困难,因为你需要查询S3以了解“自上次检查以来有什么变化”。祝玩得愉快! - Jordan
谢谢Jordan。但是真的建议我去客户端>s3吗?我正在重新考虑这个问题。除了处理上传到S3的另一个API(Amazon API)之外,似乎我不会得到任何好处。因此,如果我通过服务器上传然后上传到s3,那么感觉会更清洁。具有这样的优势,我可以立即向数据库添加条目(因为我需要为每个上传的图像添加条目)。如果我选择客户端> django/ec2 > s3,是否存在任何缺点?从ec2到s3传输文件似乎不需要任何费用。你会怎么做? - n.evermind
1
我在业务中所做的是上传到我的Web服务器。文件被存储在临时存储中,并稍后由处理服务接收。我使用Celery实现了这一点。这样做的好处是我的客户不必等待上传完成。缺点是它增加了一层复杂性。正如我在之前的评论中提到的,如果您确实想直接访问S3,您可以定期检查S3以查看最近上传的内容,以便将其添加到数据库中。 - Jordan

1
你可能想看看django-storages。它可以方便地将文件存储在S3和其他一些服务/平台上。

谢谢Keith。我刚刚查看了一些其他帖子,似乎我应该直接从客户端(iPhone)上传到S3,而不是通过Django。在这种情况下,我想我就不需要django-storages了。但还是感谢你让我知道。 - n.evermind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接