【问题标题】:Flask Upload Image to S3 without saving it to local file systemFlask 将图像上传到 S3 而不将其保存到本地文件系统
【发布时间】:2021-06-22 06:47:40
【问题描述】:

我需要将用户提交的照片上传到 s3 存储桶。但是我不断收到以下错误:

TypeError: expected str, bytes or os.PathLike object, not FileStorage

如何将文件存储为字符串/字节而不是 FileStorage?相关代码如下:

@user_api.route('upload-profile-photo', methods=['PUT'])
@Auth.auth_required
def upload_profile_photo():
  """
  Upload User Profile Photo
  """
  key = Auth.auth_user()
  bucket = 'profile-photos'
  content_type = request.mimetype
  image_file = request.files['file']
  client = boto3.client('s3',
                        region_name='sfo2',
                        endpoint_url='https://example.xxx.amazonaws.com',
                        aws_access_key_id=os.environ['ACCESS_KEY'],
                        aws_secret_access_key=os.environ['SECRET_KEY'])
  with open(image_file, "rb") as f:
    client.upload_fileobj(
        bucket,
        f,
        key,
        ExtraArgs={'ACL': 'public-read', 'ContentType': content_type}
    )

  return custom_response({'message': 'image uploaded'}, 200)

【问题讨论】:

    标签: flask boto3


    【解决方案1】:

    我要使用FileStorage 来实现这一点,我使用put_object() 的方法:

    from werkzeug import secure_filename
    
    @user_api.route('upload-profile-photo', methods=['PUT'])
    @Auth.auth_required
    def upload_profile_photo():
        """
        Upload User Profile Photo
        """
        key = Auth.auth_user()
        bucket = 'profile-photos'
        content_type = request.mimetype
        image_file = request.files['file']
    
        client = boto3.client('s3',
                              region_name='sfo2',
                              endpoint_url='https://example.xxx.amazonaws.com',
                              aws_access_key_id=os.environ['ACCESS_KEY'],
                              aws_secret_access_key=os.environ['SECRET_KEY'])
    
        filename = secure_filename(image_file.filename)  # This is convenient to validate your filename, otherwise just use file.filename
    
        client.put_object(Body=image_file,
                          Bucket=bucket,
                          Key=filename,
                          ContentType=content_type)
    
        return custom_response({'message': 'image uploaded'}, 200)
    
    

    注意对secure_filename() 的调用是可选的(您可以简单地传递image_file.filename),但可以非常方便地验证文件名。 否则添加一些异常处理会很好,但粗略的想法在这里:不需要open()文件(需要存储在本地)。

    我鼓励您查看the documentation here,以了解与upload_fileobj() 的区别

    【讨论】:

    • 我想我误解了函数 put.object 和 upload_fileobj。你的建议奏效了。谢谢!
    • 您是说secure_filename(image_file.filename) 吗?我看不到在哪里创建了 file 变量。
    【解决方案2】:
      import boto3   
      s3 = boto3.client(
                "s3",
                aws_access_key_id= "*************",
                aws_secret_access_key="**********"
            ) 
    
      @login_blueprint.route('/uploadfile', methods=['POST'])
             file= request.files['file']
            
             try:
                        filename = secure_filename(file.filename)
                        acl="public-read"
                        s3.upload_fileobj(
                            file,
                            'bucket-name',
                            file.filename,
                            ExtraArgs={
                                "ACL": acl,
                                "ContentType":  file.content_type
                            }
                        )
            
             except Exception as e:
                        resp = jsonify(e)
                        resp.status_code =200
                        return resp
    

    【讨论】:

      猜你喜欢
      • 2018-06-30
      • 2021-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-04
      • 2012-08-10
      相关资源
      最近更新 更多