通过Chalice API调用将文件上载到AWS S3

JCh*_*hao 9 python python-3.x boto3 chalice

我正试图通过Chalice将文件上传到我的S3存储桶(我现在正在玩它,对此仍然是新手).但是,我似乎无法做到正确.

我正确地设置了AWS,成功完成了本教程后回复了一些消息.然后我尝试做一些上传/下载,问题出现了.

s3 = boto3.resource('s3', region_name=<some region name, in this case oregon>)
BUCKET= 'mybucket'
UPLOAD_FOLDER = os.path.abspath('')  # the file I wanna upload is in the same folder as my app.py, so I simply get the current folder name

@app.route('/upload/{file_name}', methods=['PUT'])
def upload_to_s3(file_name):
    s3.meta.client.upload_file(UPLOAD_FOLDER+file_name, BUCKET, file_name)
    return Response(message='upload successful',
                    status_code=200,
                    headers={'Content-Type': 'text/plain'}
    )
Run Code Online (Sandbox Code Playgroud)

请不要担心我如何设置文件路径,当然,除非这是问题.

我收到了错误日志:

没有相应的文件和目录: ''

在这种情况下file_name只是mypic.jpg.

我想知道为什么这UPLOAD_FOLDER部分没被拿起来.另外,作为参考,似乎使用绝对路径对于Chalice来说会很麻烦(在测试时,我看到代码被移动到/var/task/)

有谁知道如何正确设置它?

编辑:

完整的脚本

from chalice import Chalice, Response

import boto3

app = Chalice(app_name='helloworld')  # I'm just modifying the script I used for the tutorial 
s3 = boto3.client('s3', region_name='us-west-2')
BUCKET = 'chalicetest1'

@app.route('/')
def index():
    return {'status_code': 200,
            'message': 'welcome to test API'}

@app.route('/upload/{file_name}, methods=['PUT'], content_types=['application/octet-stream'])
def upload_to_s3(file_name):
    try:
        body = app.current_request.raw_body
        temp_file = '/tmp/' + file_name
        with open(temp_file, 'wb') as f:
            f.write(body)
        s3.upload_file(temp_file, BUCKET, file_name)
        return Response(message='upload successful',
                        headers=['Content-Type': 'text/plain'],
                        status_code=200)
    except Exception, e:
        app.log.error('error occurred during upload %s' % e)
        return Response(message='upload failed',
                        headers=['Content-Type': 'text/plain'],
                        status_code=400)
Run Code Online (Sandbox Code Playgroud)

bas*_*flp 13

我得到它运行,这对我来说像app.pyAWS Chalice项目中一样:

from chalice import Chalice, Response
import boto3

app = Chalice(app_name='helloworld')

BUCKET = 'mybucket'  # bucket name
s3_client = boto3.client('s3')


@app.route('/upload/{file_name}', methods=['PUT'],
           content_types=['application/octet-stream'])
def upload_to_s3(file_name):

    # get raw body of PUT request
    body = app.current_request.raw_body

    # write body to tmp file
    tmp_file_name = '/tmp/' + file_name
    with open(tmp_file_name, 'wb') as tmp_file:
        tmp_file.write(body)

    # upload tmp file to s3 bucket
    s3_client.upload_file(tmp_file_name, BUCKET, file_name)

    return Response(body='upload successful: {}'.format(file_name),
                    status_code=200,
                    headers={'Content-Type': 'text/plain'})
Run Code Online (Sandbox Code Playgroud)

您可以使用curl对其进行测试,--upload-file直接从命令行进行测试:

curl -X PUT https://YOUR_API_URL_HERE/upload/mypic.jpg --upload-file mypic.jpg --header "Content-Type:application/octet-stream"
Run Code Online (Sandbox Code Playgroud)

要使其运行,您必须手动附加策略以将s3写入 lambda函数的角色.此角色由Chalice自动生成.将策略(例如AmazonS3FullAccess)手动附加AWS IAM Web界面中现有策略旁边的Chalice项目创建的角色.

值得一提的是:

  • 你不能写入/var/task/Lambda函数的工作目录,但是你有一些空间/tmp/,请参阅这个答案.
  • 你必须指定接受的内容类型'application/octet-stream'@app.route(并相应地上传文件通过curl).
  • HTTP PUT将文件或资源放在特定的URI中,因此要使用PUT,必须通过HTTP将此文件上载到API.