Как скачать файл с AWS Lambda Python Rest API - PullRequest
1 голос
/ 14 апреля 2020

Итак, я пытался загрузить файл из корзины s3 через python rest api, размещенный в AWS. Я следовал шаблону надлежащего API для отдыха в такой среде , используя это видео . Однако я совершенно не представляю, как передать файл в ответ. Вот мой код:

import json, traceback, boto3
from AWSHelper import DynamoDBHelper, S3Helper

dynamodbH = DynamoDBHelper()
s3H = S3Helper('vini-bucket2')

def lambda_handler(event, context):
    response = {}
    response['headers'] = {}
    try:
        for key in event['queryStringParameters']:
            try:
                event['queryStringParameters'][key] = int(event['queryStringParameters'][key])
            except:
                pass
        fn = dynamodbH.select('files', event['queryStringParameters'])['FileName']
        s3client = boto3.client('s3')
        fileobj = s3client.get_object(Bucket=s3H.bucket,Key=fn) 
        filedata = fileobj['Body'].read()
        response['statusCode'] = 200
        response_type = fn.split('.')[-1]
        response['headers']['Content-Type'] = f'application/{response_type}'
        # the problem starts here. None of these solutions work: 
        #response['body'] = json.dumps(filedata) -> Object of type bytes is not JSON serializable
        #response['body'] = filedata.decode(encoding='UTF-8') -> 'utf-8' codec can't decode byte 0x9c in position 146: invalid start byte
        #response['body'] = filedata  -> 'utf-8' codec can't decode byte 0x9c in position 146: invalid start byte
    except Exception as ex:
        response['statusCode'] = 500
        response['headers']['Content-Type'] = 'application/json'
        tr = {}
        tr['Type'] = str(type(ex))
        tr['Message'] = ex.message if hasattr(ex, 'message') else str(ex)
        tr['StackTrace'] = str(traceback.format_exc())
        tr['Pameters'] = event['queryStringParameters']
        response['body'] = json.dumps(tr)
    except:
        response['statusCode'] = 500
        response['headers']['Content-Type'] = 'application/json'
        tr = {}
        tr['Message'] = 'Unexpected error'
        response['body'] = json.dumps(tr)
    return response

1 Ответ

1 голос
/ 14 апреля 2020

Вам не нужно возвращать файл, просто создайте предварительно подписанный URL-адрес для загрузки и перенаправьте его. Согласно boto3 docs , должно быть что-то вроде этого:

s3_client = boto3.client('s3')
presign_url = s3_client.generate_presigned_url('get_object',
                                                Params={'Bucket': bucket_name,
                                                        'Key': object_name},
                                                ExpiresIn=expiration)

response["headers"]["Location"] = presign_url
return response

И это должно сделать, ответ перенаправит запрос к объекту, и он должен быть загружен.

...