Django:如何允许可疑文件操作/复制文件

tja*_*ati 5 python django

我想做一个SuspiciousFileOperationdjango默认不允许的.

我正在编写一个命令(运行manage.py importfiles)以在我自己编写的Django文件存储库中导入真实文件系统上的给定目录结构.

我想,这是我的相关代码:

def _handle_directory(self, directory_path, directory):
    for root, subFolders, files in os.walk(directory_path):
        for filename in files:
            self.cnt_files += 1
            new_file = File(directory=directory, filename=filename, file=os.path.join(root, filename),
                 uploader=self.uploader)
            new_file.save()
Run Code Online (Sandbox Code Playgroud)

回溯是:

Traceback (most recent call last):
  File ".\manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "C:\Python27\lib\site-packages\django\core\management\__init__.py", line 399, in execute_from_command_line
    utility.execute()
  File "C:\Python27\lib\site-packages\django\core\management\__init__.py", line 392, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Python27\lib\site-packages\django\core\management\base.py", line 242, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "C:\Python27\lib\site-packages\django\core\management\base.py", line 285, in execute
    output = self.handle(*args, **options)
  File "D:\Development\github\Palco\engine\filestorage\management\commands\importfiles.py", line 53, in handle
    self._handle_directory(args[0], root)
  File "D:\Development\github\Palco\engine\filestorage\management\commands\importfiles.py", line 63, in _handle_directory
    new_file.save()
  File "D:\Development\github\Palco\engine\filestorage\models.py", line 157, in save
    self.sha512 = hashlib.sha512(self.file.read()).hexdigest()
  File "C:\Python27\lib\site-packages\django\core\files\utils.py", line 16, in <lambda>
    read = property(lambda self: self.file.read)
  File "C:\Python27\lib\site-packages\django\db\models\fields\files.py", line 46, in _get_file
    self._file = self.storage.open(self.name, 'rb')
  File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 33, in open
    return self._open(name, mode)
  File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 160, in _open
    return File(open(self.path(name), mode))
  File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 261, in path
    raise SuspiciousFileOperation("Attempted access to '%s' denied." % name)
django.core.exceptions.SuspiciousFileOperation: Attempted access to 'D:\Temp\importme\readme.html' denied.
Run Code Online (Sandbox Code Playgroud)

完整的模型可以在GitHub上找到.在目前完整的命令是可用gist.github.com.

如果您不想检查模型:file我的File类的属性是FileField.

我假设,这个问题发生了,因为我只是"链接"到找到的文件.但是我需要复制它,对吧?如何将文件复制到文件中?

use*_*513 9

我没有遇到类似的问题但相关的问题。我最近将 Django 1.8 升级到 1.11。

现在,如果尝试将文件保存在具有 FileField 字段的模型中,我会收到以下错误:

/api/send_report/ 处的 SuspiciousFileOperation 连接的路径 (/vagrant/tmp/test_file.pdf) 位于基本路径组件 (/vagrant/media) 之外

我想要保存文件的模型:

class Report(BaseModel):
    file = models.FileField(max_length=200, upload_to=os.path.join(settings.REPORTS_URL, '%Y/week_%W/'))
    type = models.CharField(max_length=20, verbose_name='Type', blank=False, default='', db_index=True)
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用以下代码来保存不位于 MEDIA_ROOT 中的 tmp 文件夹中的文件:

from django.core.files import File

filepath = "/vagrant/tmp/test_file.pdf"
file = File(open(filepath, "rb"))
report_type = "My_report_type"
report = Report.objects.create(
    file=file,
    type=report_type,
)
Run Code Online (Sandbox Code Playgroud)

我为解决该问题所做的事情:

import os
from django.core.files import File

filepath = "/vagrant/tmp/test_file.pdf"
file = File(open(filepath, "rb"))
file_name = os.path.basename(file.name)
report_type = "My_report_type"
report = Report.objects.create(
    type=report_type,
)
report.file.save(file_name, file, save=True)
Run Code Online (Sandbox Code Playgroud)

希望它能帮助某人。


小智 6

在 Django 中,可以通过从外部目录读取文件并在项目媒体中创建一个 tmp 文件然后保存在适当的文件中来避免 SuspiciousFileOperation,如下所示

import tempfile

file_name="file_name.pdf"
EXT_FILE_PATH = "/home/somepath/"
file_path = EXT_FILE_PATH + file_name
if exists(file_path):
    #create a named temporary file within the project base , here in media

    lf = tempfile.NamedTemporaryFile(dir='media')
    f = open(file_path, 'rb')
    lf.write(f.read())
    #doc object with file FileField.

    doc.file.save(file_name, File(lf), save=True)
    lf.close()
Run Code Online (Sandbox Code Playgroud)


paj*_*ton 5

分析堆栈跟踪的这一部分:

File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 261, in path
    raise SuspiciousFileOperation("Attempted access to '%s' denied." % name)
Run Code Online (Sandbox Code Playgroud)

导致标准的Django FileSystemStorage。它期望文件位于您的MEDIA_ROOT。您的文件可以在文件系统中的任何位置,因此会发生此问题。

您应该传递类似文件的对象,而不是File模型的路径。最简单的方法是使用Django File类,该类是类似python文件的对象的包装。有关更多详细信息,请参见文件对象文档

更新:

好的,我建议从文档中选择一条路线:

from django.core.files import File as FileWrapper

def _handle_directory(self, directory_path, directory):
    for root, subFolders, files in os.walk(directory_path):
        for filename in files:
            self.cnt_files += 1
            new_file = File(
                 directory=directory, filename=filename,
                 file=os.path.join(root, filename),
                 uploader=self.uploader)
            with open(os.path.join(root, filename), 'r') as f:
                file_wrapper = FileWrapper(f)
                new_file = File(
                    directory=directory, filename=filename,
                    file=file_wrapper,
                    uploader=self.uploader)
                new_file.save()
Run Code Online (Sandbox Code Playgroud)

如果可行,则应将文件复制到secure_storage可调用对象提供的位置。