【问题标题】:Django: How to allow a Suspicious File Operation / copy a fileDjango:如何允许可疑文件操作/复制文件
【发布时间】:2014-03-27 23:33:20
【问题描述】:

我想做一个SuspiciousFileOperation django 默认不允许的。

我正在编写一个命令(通过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()

回溯是:

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.

full model can be found at GitHubfull command is currently on gist.github.com available

如果您不想检查模型:我的File 类的属性fileFileField

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

【问题讨论】:

  • Django 中导致问题的相关位置是什么?您只在代码中包含了一部分,我很确定您不会自己提出 SuspiciousOperation :)?
  • 我将完整的 backstrace 添加到我的问题中。
  • 我创建了一个后续问题:stackoverflow.com/questions/22038762/…

标签: python django


【解决方案1】:

检查文件路径前是否有斜线

file_item = models.FileField(upload_to=content_file_name)


def content_file_name(username, filename):
    return '/'.join(['content', username, filename])

注意这里"content" 不是"/content"。这就是我的问题。

【讨论】:

  • 不,这不是解决方案 :( 我在读取要导入的文件时遇到问题。
  • @tjati - 当文件路径前有一个“/”时我遇到了类似的错误,我通过删除它(/)来修复它,认为它会对你有所帮助......
【解决方案2】:

分析这部分stacktrace:

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

通向标准 Django FileSystemStorage。它希望文件在您的MEDIA_ROOT 内。您的文件可以位于文件系统中的任何位置,因此会出现此问题。

您应该将类​​似文件的对象而不是路径传递给您的File 模型。实现这一目标的最简单方法是使用 Django File 类,它是 Python 类文件对象的包装器。详情请见File object documentation

更新:

好的,我在这里建议从文档中获取的路线:

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

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

【讨论】:

  • 好的,第一段我明白了。但是我不明白如何调用Django的File模型以及复制操作是如何工作的。
  • 已更新以包含有关该部分的更多详细信息。让我知道这是否有帮助。
  • 好的,非常感谢!它有帮助,复制文件确实有效!不过,我有一个新问题:(这是个例外:django.db.utils.ProgrammingError: You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str ). It is highly recommended that you instead just switch your application to Unicode strings. - 我更新了我的问题,如果你能调查一下,我会接受它。
  • 很高兴它成功了!这是一个非常独立的问题,你真的应该发布关于它的新问题。能否提供失败的SQL?
  • 谢谢。你是对的,这是一个新问题。发帖后我也是这么想的。所以我恢复了我在这个问题上的最后一次更新,并将你的答案标记为正确,因为它是正确的。我重新发布了我的新问题:stackoverflow.com/questions/22038762/… - 也许你会看看它。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

    SuspiciousFileOperation 在 /api/send_report/ 连接路径(/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)
    

    我正在尝试使用以下代码从不位于 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,
    )
    

    我为解决问题所做的工作:

    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)
    

    希望对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-22
      • 2020-08-08
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多