AWS Lambda загрузить файл на s3
У меня есть лямбда-функция AWS, которая принимает данные из нескольких частей, анализирует их для документа (может быть.pdf,.doc или.docx), а затем загружает их в корзину S3. Я получаю данные формы, анализирую их и, по- видимому, просто загружаю. Однако, когда я иду, чтобы загрузить файл, он не может быть открыт, если это.doc или.docx, если это.pdf, это просто пустая страница. По сути, файлы повреждены где-то в конвейере процесса. На данный момент я действительно не знаю, что я делаю неправильно. Шаги передачи данных таковы:
- Форма загружена на стороне клиента и закодирована в base64
FormData
объект (JS) - Форма отправляется через jQuery ajax
form.js
$.ajax({
type: 'POST',
processData: false,
url: `${API_BASE}/applications`,
contentType: false,
data: formData,
success: (data) => {
isFormValid = true;
callback();
},
error: (err) => {
console.log(err);
}
});
- Соответствующий маршрут Python API (построенный с помощью Chalice) обрабатывает его
route.py
import arrow
import boto3
import cgi
from io import BytesIO
from app import app, verify_token
from chalice.app import Request
from chalicelib.core.constants import aws_credentials
s3_path: str = 'tmp/'
s3_metrics_file: str = 'metrics.json'
s3_metrics_key: str = s3_path + s3_metrics_file
# Just testing different ways to instantiate client
s3_client = boto3.client("s3", **aws_credentials)
s3_resource_client = boto3.resource("s3", **aws_credentials)
company_name = 'company'
def _get_parts(current_request) -> dict:
"""Parse multipart form data"""
raw_file: bytearray = BytesIO(current_request.raw_body)
content_type = current_request.headers['content-type']
_, parameters = cgi.parse_header(content_type)
parameters['boundary'] = parameters['boundary'].encode('utf-8')
parsed: dict = cgi.parse_multipart(raw_file, parameters)
return parsed
@app.route('/applications', cors=True, content_types=['multipart/form-data'], methods=['POST'])
def create_application() -> dict:
"""Creates an application object, stores it and sends an email with the info"""
current_request: Request = app.current_request
# Resume has to stay as bytes
body: dict = {k: v[0].decode() if k != 'resume' else v[0] for (k, v) in _get_parts(current_request).items()}
resume: bytes = body.get('resume', None)
file_name: str = body.get('file_name')
portfolio: str = body.get('portfolio', None)
file_name_new: str = f'{first_name}_{last_name}_{arrow.utcnow().format("YYYY-MM-DD")}.{file_name.split(".")[-1]}'
file_location: str = f'https://s3.amazonaws.com/{company_name}-resumes/{file_name_new}' if resume else None
s3_client.put_object(Body=resume, Bucket=company_name, Key=file_name_new)
# Different way to do the same thing
# s3_resource_client.Bucket('52inc-resumes').put_object(Key='test.jpg', Body=resume)
Нет ошибок, происходящих ни на стороне клиента, ни на стороне сервера. Похоже, это проблема перевода кодировки, переход от base64 к байту в файл на s3. Как я могу исправить эту проблему?
1 ответ
Я решил эту проблему, просто используя json со строкой base64, не более multipart/form-data
или JavaScript FormData
объект. Оттуда я мог бы просто разобрать строку base64 и отправить ее на S3. Все равно было бы интересно, если есть способ использовать multipart/form-data
для этого все же.