使用Django将异步文件上载到Amazon S3

时间:2009-03-22 02:29:32

标签: python django amazon-s3

我正在使用此文件存储引擎在上传文件时将文件存储到Amazon S3:

http://code.welldev.org/django-storages/wiki/Home

上传需要相当长的时间,因为在将响应返回给客户端之前,必须先将文件从客户端上传到Web服务器,然后再将Web服务器上载到Amazon S3。

我想将文件发送到S3异步的过程,因此可以更快地将响应返回给用户。使用文件存储引擎执行此操作的最佳方法是什么?

感谢您的建议!

7 个答案:

答案 0 :(得分:24)

我采取了另一种方法解决这个问题。

我的模型有2个文件字段,一个使用标准文件存储后端,另一个使用s3文件存储后端。当用户上传文件时,它会被存储在本地。

我的应用程序中有一个管理命令,它将所有localy存储的文件上传到s3并更新模型。

因此,当一个请求来到该文件时,我检查模型对象是否使用s3存储字段,如果是,我将重定向发送到s3上的正确URL,如果不是,我发送重定向,以便nginx可以服务于来自磁盘的文件。

这个管理命令可以由cronjob或其他任何事件触发。

答案 1 :(得分:22)

您的用户可以使用特殊表单(隐藏字段中包含加密的策略文档)从浏览器直接将文件上传到S3。上传完成后,它们将被重定向回您的应用程序。

此处提供更多信息:http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1434

答案 2 :(得分:18)

有一个应用程序: - )

https://github.com/jezdez/django-queued-storage

它完全符合您的需求 - 更重要的是,因为您可以设置任何“本地”存储和任何“远程”存储。此应用程序将您的文件存储在快速“本地”存储(例如MogileFS存储)中,然后使用Celery(django-celery),将尝试异步上载到“远程”存储。

几点评论:

  1. 棘手的是 - 您可以将其设置为复制和上传,或上传和删除策略,这将在上传后删除本地文件。

  2. 第二件棘手的事情 - 它将从“本地”存储中提供文件,直到它没有上传。

  3. 它还可以配置为在上传失败时重试次数。

  4. 安装&用法也非常简单直接:

    pip install django-queued-storage
    

    附加到INSTALLED_APPS

    INSTALLED_APPS += ('queued_storage',)
    
    models.py中的

    from queued_storage.backends import QueuedStorage
    queued_s3storage = QueuedStorage(
        'django.core.files.storage.FileSystemStorage',
        'storages.backends.s3boto.S3BotoStorage', task='queued_storage.tasks.TransferAndDelete')
    
    class MyModel(models.Model):
        my_file = models.FileField(upload_to='files', storage=queued_s3storage)
    

答案 3 :(得分:6)

你可以解耦这个过程:

  • 用户选择要上传的文件并将其发送到您的服务器。在此之后,他看到一个页面“感谢您上传foofile.txt,它现在存储在我们的存储后端”
  • 当用户上传文件时,它会在您的服务器上存储临时目录,如果需要,还会在您的数据库中存储一些元数据。
  • 服务器上的后台进程然后将文件上载到S3。这只有在您拥有对服务器的完全访问权限的情况下才有可能,因此您可以为此创建某种“deamon”(或者只是使用cronjob)。*
  • 显示的页面异步轮询并向用户显示某种进度条(或简单的“请稍候”消息。仅当用户应该能够“使用”(将其放入消息,或类似的东西)它直接上传后。

[*:如果您只有共享主机,您可以构建一些解决方案,在用户浏览器中使用隐藏的Iframe启动脚本然后将文件上传到S3]

答案 4 :(得分:3)

您可以直接将媒体上传到s3服务器,而无需使用Web应用程序服务器。

请参阅以下参考资料:

Amazon API参考:http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?UsingHTTPPOST.html

django实施:https://github.com/sbc/django-uploadify-s3

答案 5 :(得分:0)

由于这里的一些答案建议直接上传到S3,这里是使用plupload的Django S3 Mixin: https://github.com/burgalon/plupload-s3mixin

答案 6 :(得分:0)

我上传的图片遇到了同样的问题。您无法将文件传递给Celery工作程序,因为Celery需要能够为任务挑选参数。我的解决方案是将图像数据解构为字符串并从文件中获取所有其他信息,将此数据和信息传递给任务,我在其中重建图像。之后,您可以将其保存,然后将其发送到您的存储后端(例如S3)。如果要将图像与模型关联,只需将实例的id传递给任务并在那里检索它,将图像绑定到实例并保存实例。

当通过表单上传文件时,它在您的视图中可用作UploadedFile文件类对象。您可以直接从request.FILES中获取它,或者更好地首先将其绑定到您的表单,运行is_valid并从form.cleaned_data中检索类文件对象。至少你知道它是你想要它的那种文件。之后,您可以使用read()获取数据,并使用其他方法/属性获取其他信息。见https://docs.djangoproject.com/en/1.4/topics/http/file-uploads/

我实际上最终编写并分发了一个小包来异步保存图像。看一下https://github.com/gterzian/django_async它就是图像的权利,你可以分叉并为你的情况增加功能。我正在使用https://github.com/duointeractive/django-athumb和S3