Python and Django - 如何在内存和临时文件中使用

Python and Django - How to use in memory and temporary files

我需要一些在内存和临时文件中使用文件操作的示例。

我搜索了很多很好的例子/教程,我只找到了基本的 read/write/append 操作。

我需要了解如何在 Django 中读取在保存 (post) 完成之前上传的文件(图像)。

因为Django是Python,我觉得先了解一下python.

我检查了 Django documentation/examples,但不是很清楚所以我需要先了解 Python 然后在 Django 中操作是如何工作的,而不仅仅是复制和粘贴。

我知道如何使用ImageFields,上传默认操作,我只对使用“内存和临时文件”感兴趣。

我想将它与裁剪功能结合使用。因此用户可以上传 1、2、3... 图像,并使用 javascript 裁剪脚本我在隐藏字段中获取坐标。在 javascript 模拟裁剪后,我向用户展示裁剪后的缩略图,比例

用户可以改变主意,可以 edit/update 或在保存前删除文件。

现在根据文件大小,它可以保存在内存中或写入。

您可以设置用于 Django 表单的上传处理程序:https://docs.djangoproject.com/en/1.11/ref/files/uploads/#module-django.core.files.uploadhandler

有两个内置选项:

Django 的工作方式似乎是遍历所有上传处理程序的列表:https://docs.djangoproject.com/en/1.11/topics/http/file-uploads/#upload-handlers

对于每个上传处理程序,它将检查特定条件,如果该条件为真,它将激活并使用该上传处理程序。

例如,InMemoryUploadHandler 在文件小于一定大小时被激活和使用。 TemporaryFileUploadHandler 用于文件很大的时候。

您将能够从 request 对象访问数据和文件。

如果您正在查看 Python 特定的(不是 Django),那么听起来您可能对 tempfile 模块感兴趣:

https://docs.python.org/3/library/tempfile.html

改编上述文档中的示例:

import tempfile

fp = tempfile.TemporaryFile()
fp.write(b'Hello world!')
# Closing automatically deletes the tempfile
fp.close()

您可以看到这与通用 read/write 文件操作非常相似。

如果我理解正确,您正在寻找一种在使用 instance.save() 或类似方法保存上传文件之前访问它的方法。

如果是这样,您可以尝试直接从请求中读取文件:

if my_form.is_valid():
    data = request.FILES['myfile'].read()

上传文件时,Django 将执行以下两项操作之一:如果文件较小(我上次检查时小于 2 MB),则将其存储在内存中;如果文件较大,则将其作为临时文件存储在磁盘上。此行为可通过 FILE_UPLOAD_HANDLERS 设置进行配置。因此,您的网络服务器和 Django 负责实际的上传和存储,但在请求结束之前处理文件是您的工作,否则文件将被删除。

上传的文件可以通过 request.FILES 属性 访问。 FILES 中的每个键都将与您在 <form> 上输入的文件名相匹配。该值是一个 UploadedFile 对象,它是一个可用于读取文件数据的流。

例如,假设您有一个 <input name="img" type="file" /> 并且您想要检测图像是否全白。你不需要为此存储文件,你只需要将它加载到内存中,处理它得到结果然后让它被丢弃。

from PIL import Image

def some_view(request):
    if request.method == 'POST':
        img_file = request.FILES['img']

        if img_file.size > 2000000:
            return HttpResponseBadRequest()

        img = Image.open(img_file)

        # analyze the image...

另一种可能是有人正在上传一个非常大的备份文件(比如 2 GB),您需要将其存储在某个地方。这实际上是一回事,只是我们将文件分块读入内存,然后将每个块写入其他地方的磁盘,以便在请求完成后保存。

def some_view(request):
    if request.method == 'POST':
        backup_file = request.FILES['backup_file']
        with open('some/file/name.bak', 'wb+') as destination:
            for chunk in backup_file.chunks():
                destination.write(chunk)

        # file is saved

请求结束后,上传的文件存储在some/file/name.bak

它是在内存中还是在临时文件中通常并不重要,因为接口是相同的。您可以像读取内存文件一样读取临时文件。