在Django/python中操作和创建S3文件时需要本地系统文件
我正在使用django-storages把媒体文件存储在S3桶里。不过,有时候我需要转换文件或者对文件进行一些操作,这些操作必须在我的服务器上进行(大部分转换是通过进程调用来完成的)。完成后,我想把这些文件再保存回S3。
理想情况下,我希望在从本地转到S3时,不需要对我的函数做任何修改。但是,我不太确定该怎么做,因为我需要先创建这些临时的本地文件来进行操作,然后最后还要把生成的文件(也会存储在本地)复制到S3。
我想到的最好办法是使用一对上下文管理器,一个用于源文件,一个用于目标文件。源文件的管理器会创建一个临时文件,把源文件的内容复制到这个临时文件中,然后就可以对这个临时文件进行操作。目标文件的管理器则会获取S3上最终想要的目标路径,并创建一个临时的本地文件,退出时会在S3桶中创建一个键,把临时文件的内容复制过去,然后再删除这个临时文件。
但对我来说,这似乎有点复杂。而且这还要求我把每一个处理这些文件的函数都包裹在两个“with”语句中。
我能想到的唯一其他解决方案是切换到只处理类文件对象的工具,而不是文件名,但这样的话我就不能进行子进程调用了。
1 个回答
看看这个内置的 文件存储API - 这正是它的用武之地。
如果你在使用django-storages并且要上传到S3,那么在你的设置文件中应该有一行像这样:
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
当你在本地开发时,如果不想把媒体文件上传到S3,在你的本地设置文件中,可以把这行去掉,这样就会默认使用 django.core.files.storage.FileSystemStorage
。
在你的应用代码中,对于那些在你从本地开发转到测试环境时要保存到S3的媒体文件,使用 get_storage_class
函数返回的类来创建一个 Storage
对象,然后用这个对象来处理文件。对于那些你在本地“摆弄”的临时文件,不要使用这个 Storage
对象(也就是说,使用Python内置的文件处理函数),除非是你想要保存到S3的文件。
当你准备好开始在S3上保存文件时,只需再次设置 DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
,你的代码就会正常工作,不需要其他调整。当这个设置没有被设置时,这些媒体文件会被保存在本地文件系统的 MEDIA_ROOT
下,同样不需要改变你的应用逻辑。