将本地创建的 csv 文件保存到 s3 存储桶时的 Django.core.exceptions.SuspiciousOperation

问题描述 投票:0回答:1

我需要使用 django python 创建 csv 报告,然后将其保存到模型上的 FileField 中。文件字段将其存储到安全的亚马逊存储桶中。这是我用于模型的逻辑:

class MyModel(models.Model):
created_on = models.DateTimeField(auto_now_add=True)
the_file = models.FileField(blank=True,null=True,upload_to='some/dir/')

def save(self, *args,**kwargs):    
    super().save(*args,**kwargs)
    _access_key = settings.FINANCE_ACCESS
    _access_secret = settings.FINANCE_SECRET
    _access_bucket = settings.FINANCE_BUCKET
    s3 = boto3.client('s3', aws_access_key_id=_access_key, aws_secret_access_key=_access_secret)
    try:
        if self.the_file:
            _the_file_content = default_storage.open(self.the_file.name).read()  
s3.put_object(Body=_the_file_content,Bucket=_access_bucket,Key=self.the_file.name)
    except Exception as e:
        print(type(e),e)

使用管理站点上传文件,然后一切都按预期进行。

当我创建 csv 文件并尝试从视图中以编程方式保存模型时,事情开始变得棘手。这就是我正在做的事情:

def create_and_save_the_file():
    from tbkpayments.models import MyModel
    import os,csv,tempfile,sys
    _add_random_line = ['this','is','a','line']
    csv_file_name='file.csv'
    csv_file_path = os.path.join(tempfile.gettempdir(), csv_file_name)
    csv_file = open(csv_file_path, 'w')
    csv_writer = csv.writer(csv_file)
    # add lines to the file
    csv_writer.writerow(_add_random_line)
    csv_writer.writerow(_add_random_line)
    csv_writer.writerow(_add_random_line)
    print(csv_file)
    print()
    csv_file.close()
    # We create the model to store the file
    _model=MyModel.objects.create()
    with open(csv_file_path, 'r') as f:
        data = f.read()
        _model.the_file.save(csv_file_path,data)
        f.close() 

////

我得到的例外是:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "<console>", line 20, in create_and_save_the_file
  File "/home/kenny/Projects/backend/virtenvs/venv/lib/python3.8/site-packages/django/db/models/fields/files.py", line 87, in save
    self.name = self.storage.save(name, content, max_length=self.field.max_length)
  File "/home/kenny/Projects/backend/virtenvs/venv/lib/python3.8/site-packages/django/core/files/storage.py", line 51, in save
    name = self.get_available_name(name, max_length=max_length)
  File "/home/kenny/Projects/backend/virtenvs/venv/lib/python3.8/site-packages/storages/backends/s3boto3.py", line 620, in get_available_name
    return super(S3Boto3Storage, self).get_available_name(name, max_length)
  File "/home/kenny/Projects/backend/virtenvs/venv/lib/python3.8/site-packages/django/core/files/storage.py", line 75, in get_available_name
    while self.exists(name) or (max_length and len(name) > max_length):
  File "/home/kenny/Projects/backend/virtenvs/venv/lib/python3.8/site-packages/storages/backends/s3boto3.py", line 516, in exists
    name = self._normalize_name(self._clean_name(name))
  File "//home/kenny/Projects/backend/virtenvs/venv/lib/python3.8/site-packages/storages/backends/s3boto3.py", line 430, in _normalize_name
    raise SuspiciousOperation("Attempted access to '%s' denied." %
django.core.exceptions.SuspiciousOperation: Attempted access to '/tmp/file.csv' denied.

我检查了 tmp/ 文件夹权限(我在 Ubuntu 20.04/lts 下),一切看起来都很好。另外,文件已创建,我可以正确访问它。我在 save() 方法中缺少什么(请注意,我正在使用 filefield.save 方法)?似乎是一个权限问题,但我不太确定(因为从管理员上传相同的内容......)

python django file boto3
1个回答
0
投票

好吧,很明显我忽略了一些东西(我使用了我的旧代码,我必须读取文件,然后将其作为 sendgrid 附件发送): 我的错误是这样的:

with open(csv_file_path, 'r') as f:
 data = f.read()  #Error here!
 _model.the_file.save(csv_file_path,**data**)
 f.close() 

相反,我只需要这样做:

with open(payroll_file_path, 'rb') as f:
 withdrawal.payroll_success_file.save(payroll_file,**f**)
 f.close()   

从 f 中读取数据,然后尝试将其存储在 FileField 中...有时出现这样的错误是件好事,这样您就可以记住保持谦虚并时不时地回到基础知识。 希望有人觉得这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.