首页 > 解决方案 > django打开的文件类型到python打开的文件类型

问题描述

我有一个要求用户上传图像的 django 应用程序。我从 html django 获取图像。我将此图像作为参数传递给 python 脚本。我对这张图片做了很多事情(比如使用 PIL 库),参数的类是:

'django.core.files.uploadedfile.InMemoryUploadedFile'

但是当我尝试使用一个要求预先确定的python .open() 类型的函数时,问题就来了,即:

'_io.BufferedReader'

具体来说,我正在使用的功能是: block_blob_service.create_blob_from_stream()(Microsoft Azure 功能)

所以我的问题是,我可以从 django 打开的文件类型转换为 python 打开的文件类型吗?可能没有保存文件并再次打开。

而且,如果有任何机会,有人使用过这个库,我也尝试过block_blob_service.create_blob_from_bytes()但它不起作用(从 django 转换为我刚刚完成img = django_input.read()的字节(我得到一个 Bytes 类型)并且block_blob_service.create_blob_from_path(), 不是一个选项,因为我无法获取文件的路径,也不想保存图像并获取新路径。

标签: pythondjangoazureblobazure-blob-storage

解决方案


仅根据 的源代码django.core.files.uploadedfile,类InMemoryUploadedFile继承自继承自的类UploadedFiledjango.core.files.base.File如下代码和图所示。

from django.core.files.base import File

class UploadedFile(File):
    """
    An abstract uploaded file (``TemporaryUploadedFile`` and
    ``InMemoryUploadedFile`` are the built-in concrete subclasses).

    An ``UploadedFile`` object behaves somewhat like a file object and
    represents some file data that the user submitted with a form.
    """

    def __init__(self, file=None, name=None, content_type=None, size=None, charset=None, content_type_extra=None):
        super().__init__(file, name)
        self.size = size
        self.content_type = content_type
        self.charset = charset
        self.content_type_extra = content_type_extra

    def __repr__(self):
        return "<%s: %s (%s)>" % (self.__class__.__name__, self.name, self.content_type)

    def _get_name(self):
        return self._name

    def _set_name(self, name):
        # Sanitize the file name so that it can't be dangerous.
        if name is not None:
            # Just use the basename of the file -- anything else is dangerous.
            name = os.path.basename(name)

            # File names longer than 255 characters can cause problems on older OSes.
            if len(name) > 255:
                name, ext = os.path.splitext(name)
                ext = ext[:255]
                name = name[:255 - len(ext)] + ext

        self._name = name

    name = property(_get_name, _set_name)

class InMemoryUploadedFile(UploadedFile):
    """
    A file uploaded into memory (i.e. stream-to-memory).
    """
    def __init__(self, file, field_name, name, content_type, size, charset, content_type_extra=None):
        super().__init__(file, name, content_type, size, charset, content_type_extra)
        self.field_name = field_name

    def open(self, mode=None):
        self.file.seek(0)
        return self

    def chunks(self, chunk_size=None):
        self.file.seek(0)
        yield self.read()

    def multiple_chunks(self, chunk_size=None):
        # Since it's in memory, we'll never have multiple chunks.
        return False

下图来自https://docs.djangoproject.com/en/2.2/ref/files/uploads/ 在此处输入图像描述

因此,您可以从InMemoryUploadedFileobject 获取数据字节并将其传递给 function block_blob_service.create_blob_from_bytes

同时,正如我所知,这不是一个好主意。在 Django 中从上传的文件创建 blob 的简单解决方案是django-storages与 Azure Storage 后端一起使用,请参阅其有关Azure Storage的文档以了解如何使用。还有现有的类似 SO thread Django Azure upload file to blob storage,你可以参考一下。


推荐阅读