1

我有一个 AWS lambda 函数,它接收多部分表单数据,将其解析为文档(可以是 .pdf、.doc 或 .docx),然后将其上传到 S3 存储桶。我正在接收表单数据,对其进行解析并似乎可以正常上传。但是,当我去下载文件时,如果它是 .doc 或 .docx,则无法打开它,如果它是 .pdf,它只是一个空白页。本质上,文件在流程管道中的某处被损坏。在这一点上,我真的不知道我做错了什么。数据传输步骤如下:

  1. 表单在客户端上传并在FormData对象 (JS)中进行 base64 编码
  2. 表单通过 jQuery ajax 发送

表单.js

$.ajax({
    type: 'POST',
    processData: false,
    url: `${API_BASE}/applications`,
    contentType: false,
    data: formData,
    success: (data) => {
        isFormValid = true;
        callback();
    },
    error: (err) => {
        console.log(err);
    }
});
  1. 相应的 Python API(用Chalice构建)路由处理它

路线.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 上的文件。我该如何纠正这个问题?

4

1 回答 1

1

我最终通过简单地使用带有 base64 字符串的 json 来解决这个问题,不再multipart/form-data使用 JavaScriptFormData对象。从那里我可以简单地解析出 base64 字符串并将其发送到 S3。不过,如果有办法使用它,仍然会感兴趣multipart/form-data

于 2018-08-23T19:21:52.660 回答