Flask Загрузить изображение на S3, не сохраняя его в локальной файловой системе - PullRequest
0 голосов
/ 22 марта 2019

Мне нужно загрузить фотографию, отправленную пользователем, в корзину 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)

1 Ответ

2 голосов
/ 22 марта 2019

Чтобы добиться этого с 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(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() файл (который должен храниться локально).

Я рекомендую взглянуть на документацию здесь , чтобы понять разницу с upload_fileobj()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...