【问题标题】:How to create a file in memory (not an uploaded file) and save to FileField through Django default_storage?如何在内存中创建文件(不是上传的文件)并通过 Django default_storage 保存到 FileField?
【发布时间】:2018-07-21 21:11:37
【问题描述】:

如果我要像这样在内存中创建一个类似文件的 csv 对象:

output_stream = io.StringIO()
sheet = pyexcel.get_sheet(records=data)
sheet.save_to_memory(file_type='csv', stream=output_stream)

如何使用 Django 将 output_stream 中的对象之类的文件保存到我的 default_storage 后端文件中?

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'>)

【问题讨论】:

  • 请发布异常的完整回溯。

标签: django python-3.x django-storage pyexcel


【解决方案1】:

您可以从StringIO 读取内容并像这样转换为 utf8 编码字节。

self.model_file.save(filename, ContentFile(output_stream.getvalue().encode()))

getvalue()read() 类似,但无论当前流位置如何,您都将始终获得 StringIO 的完整内容。使用read(),您可能需要使用seek(0) 倒带。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-06
    • 2011-11-22
    • 2014-08-09
    • 2013-04-09
    • 2010-10-25
    • 2012-11-24
    • 2013-12-26
    • 2017-12-14
    相关资源
    最近更新 更多