如何在内存中创建一个文件(不是上传的文件)并通过Django保存到FileField default_storage?
How to create a file in memory (not an uploaded file) and save to FileField through Django default_storage?
如果我要像这样在内存中创建一个类似文件的 csv 对象:
output_stream = io.StringIO()
sheet = pyexcel.get_sheet(records=data)
sheet.save_to_memory(file_type='csv', stream=output_stream)
我怎样才能将 output_stream 中的文件之类的对象保存到我的 default_storage 后端的 Django 文件中?
class Example(models.Model):
model_file = models.FileField(upload_to='', max_length=255, blank=True, null=True)
我试过类似的方法:
self.model_file.save(filename, ContentFile(output_stream.read()))
但我收到以下错误:
"TypeError: ('data must be bytes, received', <class 'str'>)"
pyexcel 仅支持 csv 类型文件的 io.StringIO 流。
回溯:
...
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\files\storage.py", line 49, in save
return self._save(name, content)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\storages\backends\gcloud.py", line 167, in _save
content_type=file.mime_type)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 1034, in upload_from_file
size, num_retries, predefined_acl)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 947, in _do_upload
size, num_retries, predefined_acl)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 759, in _do_multipart_upload
transport, data, object_metadata, content_type)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\resumable_media\requests\upload.py", line 94, in transmit
data, metadata, content_type)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\resumable_media\_upload.py", line 270, in _prepare_request
raise TypeError(u'`data` must be bytes, received', type(data))
TypeError: ('`data` must be bytes, received', <class 'str'>)
您可以从 StringIO
中读取内容并像这样转换为 utf8 编码字节。
self.model_file.save(filename, ContentFile(output_stream.getvalue().encode()))
getvalue()
类似于 read()
,但无论当前流位置如何,您将始终获得 StringIO 的完整内容。对于 read()
,您可能必须使用 seek(0)
.
倒带
如果我要像这样在内存中创建一个类似文件的 csv 对象:
output_stream = io.StringIO()
sheet = pyexcel.get_sheet(records=data)
sheet.save_to_memory(file_type='csv', stream=output_stream)
我怎样才能将 output_stream 中的文件之类的对象保存到我的 default_storage 后端的 Django 文件中?
class Example(models.Model):
model_file = models.FileField(upload_to='', max_length=255, blank=True, null=True)
我试过类似的方法:
self.model_file.save(filename, ContentFile(output_stream.read()))
但我收到以下错误:
"TypeError: ('data must be bytes, received', <class 'str'>)"
pyexcel 仅支持 csv 类型文件的 io.StringIO 流。
回溯:
...
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\files\storage.py", line 49, in save
return self._save(name, content)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\storages\backends\gcloud.py", line 167, in _save
content_type=file.mime_type)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 1034, in upload_from_file
size, num_retries, predefined_acl)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 947, in _do_upload
size, num_retries, predefined_acl)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\cloud\storage\blob.py", line 759, in _do_multipart_upload
transport, data, object_metadata, content_type)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\resumable_media\requests\upload.py", line 94, in transmit
data, metadata, content_type)
File "C:\Users\Cole\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\resumable_media\_upload.py", line 270, in _prepare_request
raise TypeError(u'`data` must be bytes, received', type(data))
TypeError: ('`data` must be bytes, received', <class 'str'>)
您可以从 StringIO
中读取内容并像这样转换为 utf8 编码字节。
self.model_file.save(filename, ContentFile(output_stream.getvalue().encode()))
getvalue()
类似于 read()
,但无论当前流位置如何,您将始终获得 StringIO 的完整内容。对于 read()
,您可能必须使用 seek(0)
.