一个类似StringIO的类,扩展django.core.files.File
class MyModel(models.Model)
image = models.FileField(upload_to="blagh blagh...")
#more spam...
我在内存中有一个文件,我想通过Django的FileField保存这个文件,像这样:
photo.image.save(name, buffer) # second arg should be django File
我试着使用StringIO,但它没有继承django.core.files.File,所以没有实现chunks()这个方法。我是这样把它包装成一个File对象的:
buffile = File(buffer, name) # first argument should be a file
photo.image.save(name, buffile)
但是File的方法使用的是提供文件的大小和名称字段,而StringIO并没有定义这些字段。我找到过这个链接,但现在链接已经失效了。
3 个回答
8
关于Jason的回答,注意到ContentFile只接受字符串,而不接受任何类似文件的对象。这里有一个可以接受的例子 --
from django.core.files.base import *
class StreamFile(ContentFile):
"""
Django doesn't provide a File wrapper suitable
for file-like objects (eg StringIO)
"""
def __init__(self, stream):
super(ContentFile, self).__init__(stream)
stream.seek(0, 2)
self.size = stream.tell()
现在你可以像这样操作 --
photo.image.save(name, StreamFile(io))
34
你可以用 ContentFile 来代替 File。
from django.core.files.base import ContentFile
photo.image.save(name, ContentFile(buffer))
8
如果你有一串字节流,想把它保存到一个文件字段或者图片字段,这里有段代码可能会对你有帮助:
>>> from django.core.files.uploadedfile import InMemoryUploadedFile
>>> from cStringIO import StringIO
>>> buf = StringIO(data) # `data` is your stream of bytes
>>> buf.seek(0, 2) # Seek to the end of the stream, so we can get its length with `buf.tell()`
>>> file = InMemoryUploadedFile(buf, "image", "some_filename.png", None, buf.tell(), None)
>>> photo.image.save(file.name, file) # `photo` is an instance of `MyModel`
>>> photo.image
<ImageFieldFile: ...>
一些小提示:
- 你可以随意给图片起个名字,但最好保持文件扩展名的正确性,比如.jpg或.png。
- 在
InMemoryUploadedFile
的第二个参数中,填入你模型里字段的名字,这里是“image”。
这个过程有点麻烦,但最终能完成任务。希望在1.3/4版本中,API能变得更简洁一些。
补充:
可以查看Jason的回答,那里面有更简单的方法,不过你还是需要知道图片的文件名。