Django FileField,如何避免长文件复制延迟?

时间:2013-02-21 08:45:27

标签: django file-upload filefield

我有以下课程:

class VideoFile(models.Model):
    media_file = models.FileField(upload_to=update_filename, null=True)

当我尝试使用以下请求上传大文件(从100mb到2Gb)时,在上传过程之后<{1>>可能需要很长时间过程。

VideoFile.save()

在我的Macbook Pro Core i7,8Gb内存中,一个300mb的上传文件大约需要20秒才能运行def upload(request): video_file = VideoFile.objects.create(uploader=request.user.profile) video_file.media_file = uploaded_file video_file.save()

我怀疑这种延迟与从video_file.save()到文件永久位置的磁盘复制操作有关?我已经通过在目标目录上运行/tmp证明了这一点,并且只要watch ls -l运行,我就可以看到文件在整个延迟期间出现并增长。

有没有办法消除此文件传输延迟?通过直接将文件上传到目标文件名或只是移动原始文件而不是复制?这不是整个站点的唯一上传操作,因此任何解决方案都需要本地化到此模型。

感谢您的任何建议!

更新:

只是进一步支持副本而不是移动的证据,我可以在上传期间video_file.save()查看从python写的watch lsof内的文件,该文件完全映射到上传进度。上传完成后,将显示另一个lsof条目,以查找随时间增长的最终文件位置。完成后,两个条目都会消失。

2 个答案:

答案 0 :(得分:1)

我要提醒的是,有很多原因导致上传到/tmp然后cp是最佳做法,并且将大型文件直接上传到目标是一项潜在的危险操作。< / p>

但是,你所要求的绝对是可能的。 Django定义upload handlers

  

您可以编写自定义处理程序来自定义Django处理文件的方式。例如,您可以使用自定义处理程序来强制执行用户级配额,动态压缩数据,渲染进度条,以及甚至直接将数据发送到另一个存储位置,而无需在本地存储

答案 1 :(得分:1)

在经过一番挖掘之后,我想出了一个解决方案。事实证明,Django的默认存储已经尝试移动文件而不是复制,它首先测试:

hasattr(content, 'temporary_file_path')

此属性存在于类TemporaryUploadedFile,它是返回到上载视图的对象,但字段本身是作为FileField.attr_class

指定的类创建的

所以我决定将FieldFileFileField子类化并插入temporary_file_path属性:

class VideoFieldFile(FieldFile):
    _temporary_file_path = None
    def temporary_file_path(self):
        return self._temporary_file_path


class VideoFileField(FileField):
    attr_class = VideoFieldFile

最后在视图中,在保存模型之前,我手动分配了临时路径:

video_file.media_file._temporary_file_path = uploaded_file.temporary_file_path()

现在这意味着我的1.1Gb测试文件在大约2-3秒内可用,而不是我之前看到的50秒左右。它还带来了额外的好处,即如果文件存在于不同的文件系统上,它似乎会回退到复制操作。

但是,作为旁注,我的网站没有使用某些网站可能用来处理较小文件上传的MemoryFileUploadHandler,所以我不确定我的解决方案可能会有多好用,但我确定它很容易检测上传文件的类并采取相应的行动。