ZipExtFile到Django文件

gui*_*nny 8 python django file

我想知道是否有办法将zip文件上传到django web服务器并将zip文件放入django数据库而不访问过程中的实际文件系统(例如将zip文件解压缩到tmp目录然后加载它们)

Django提供了一个将python文件转换为Django文件的函数,所以如果有一种方法将ZipExtFile转换为python文件,它应该没问题.

感谢帮助!

Django模型:

from django.db import models

class Foo:
    file = models.FileField(upload_to='somewhere')
Run Code Online (Sandbox Code Playgroud)

用法:

from zipfile import ZipFile 
from django.core.exceptions import ValidationError  
from django.core.files import File  
from io import BytesIO  

z = ZipFile('zipFile')
istream = z.open('subfile')
ostream = BytesIO(istream.read())
tmp = Foo(file=File(ostream))
try:
    tmp.full_clean()
except Validation, e:
    print e
Run Code Online (Sandbox Code Playgroud)

输出:

{'file': [u'This field cannot be blank.']}
Run Code Online (Sandbox Code Playgroud)

[解决方案]解决方案使用丑陋的黑客:

正如Don Quest正确指出的那样,类似文件的类(如StringIO或BytesIO)应将数据表示为虚拟文件.但是,Django File的构造函数只接受内置文件类型而不接受任何其他内容,尽管类文件类也可以完成这项工作.黑客是手动设置Django :: File中的变量:

buf = bytesarray(OPENED_ZIP_OBJECT.read(FILE_NAME))
tmp_file = BytesIO(buf)
dummy_file = File(tmp_file)   # this line actually fails
dummy_file.name = SOME_RANDOM_NAME
dummy_file.size = len(buf)
dummy_file.file = tmp_file
# dummy file is now valid
Run Code Online (Sandbox Code Playgroud)

如果您有更好的解决方案,请继续评论(自定义存储除外)

Don*_*ion 7

在不知道Django的情况下,我可以告诉你看一下"io"包.你可以这样做:

from zipfile import ZipFile
from io import StringIO
zname,zipextfile = 'zipcontainer.zip', 'file_in_archive'
istream = ZipFile(zname).open(zipextfile)
ostream = StringIO(istream.read())
Run Code Online (Sandbox Code Playgroud)

然后用你的"虚拟"ostream Stream/File做任何你想做的事情.


小智 6

有一种更简单的方法:

from django.core.files.base import ContentFile

uploaded_zip = zipfile.ZipFile(uploaded_file, 'r')  # ZipFile

for filename in uploaded_zip.namelist():
    with uploaded_zip.open(filename) as f:  # ZipExtFile
        my_django_file = ContentFile(f.read())
Run Code Online (Sandbox Code Playgroud)

使用此功能,您可以将上传到内存的文件直接转换为django文件.有关更完整的示例,假设您要将zip中的一系列图像文件上载到文件系统:

# some_app/models.py
class Photo(models.Model):
    image = models.ImageField(upload_to='some/upload/path')

...

# Upload code    
from some_app.models import Photo

for filename in uploaded_zip.namelist():
    with uploaded_zip.open(filename) as f:  # ZipExtFile
        new_photo = Photo()
        new_photo.image.save(filename, ContentFile(f.read(), save=True)
Run Code Online (Sandbox Code Playgroud)