python - 使用 python eve 将文件上传到 Amazon S3
问题描述
我正在尝试将图像上传到 S3 存储桶。我提到了eve 文档和这个 git repo。我试图通过以下方式做到这一点。
#/ run.py
```python
from eve import Eve
from flask_sslify import SSLify
import os
from eve.io.media import MediaStorage
from flask.app import Flask
from flask import current_app
import boto3
from botocore.exceptions import ClientError
from s3_out import S3Out
from bson.objectid import ObjectId
BUCKET = 'bucket'
AWS_REGION = 'region'
AWS_KEY = 'key'
AWS_SECRET = 'secret'
class S3MediaStorage(MediaStorage):
"""
MediaStorage implementation compatible with AWS S3 service.
"""
def __init__(self, app=None):
super(S3MediaStorage, self).__init__(app)
self.validate()
self.s3 = boto3.client('s3', aws_access_key_id=AWS_KEY,
aws_secret_access_key=AWS_SECRET,
region_name=AWS_REGION)
def validate(self):
""" Make sure that the application is an eve application.
instance.
"""
if self.app is None:
raise TypeError('Application object cannot be None')
if not isinstance(self.app, Flask):
raise TypeError('Application object must be a Eve application')
def exists(self, id_or_filename, resource=None):
try:
self.s3.get_object(Bucket=BUCKET, Key=id_or_filename)
except ClientError as ex:
if ex.response['Error']['Code'] == 'NoSuchKey':
return False
return True
def get(self, id_or_filename, resource=None):
try:
s3_object = self.s3.get_object(
Bucket=BUCKET, Key=str(id_or_filename))
except ClientError as ex:
return None
length = s3_object.get('ContentLength', 1500)
content_type = s3_object.get('ContentType', 'image/jpg')
last_modified = s3_object.get('LastModified', None)
assert 'Body' in s3_object
response = S3Out(s3_object['Body'].read(),
content_type, last_modified, length)
return response
def delete(self, id_or_filename, resource=None):
return self.s3.delete_object(Bucket=BUCKET, Key=id_or_filename)
def put(self, content, filename=None, content_type=None, resource=None):
_id = str(ObjectId())
self.s3.upload_fileobj(content, _id, BUCKET, ExtraArgs={
'ContentType': content_type})
return _id
if __name__ == '__main__':
app = Eve(media=S3MediaStorage)
port = int(os.environ.get("PORT", 5000))
app.run(host='0.0.0.0', port=port)
来自 repo 的 s3_out.py 文件
#/s3_out.py
from datetime import datetime
from io import BytesIO
class S3Out(object):
def __init__(self, file: bytes, content_type: str, upload_date: datetime, length: int):
self.file = file
self.content_type = content_type
self.upload_date = upload_date
self.length = length
def __iter__(self):
return BytesIO(self.file)
def read(self):
with open(self.file, mode='rb') as file:
f = file.read()
return bytearray(f)
我的 settings.py 文件
EXTENDED_MEDIA_INFO = ['content_type', 'name', 'length']
RETURN_MEDIA_AS_BASE64_STRING = False
RETURN_MEDIA_AS_URL = True
# MEDIA_BASE_URL = 'https://s3-us-west-2.amazonaws.com'
MEDIA_ENDPOINT = 'media'
logos = {
'logo': {'type': 'media'}
}
DOMAIN = {
'logos': logos,
}
我收到以下错误
[2020-08-13 16:29:56,808] ERROR in post: maximum recursion depth exceeded while calling a Python object
Traceback (most recent call last):
File "C:\Users\D.Vishal\Anaconda3\lib\site-packages\eve\methods\post.py", line 223, in post_internal
doc_issues = validator.errors
File "C:\Users\D.Vishal\Anaconda3\lib\site-packages\cerberus\validator.py", line 464, in errors
return self.error_handler(self._errors)
File "C:\Users\D.Vishal\Anaconda3\lib\site-packages\cerberus\errors.py", line 493, in __call__
self.extend(errors)
File "C:\Users\D.Vishal\Anaconda3\lib\site-packages\cerberus\errors.py", line 397, in extend
self.add(error)
File "C:\Users\D.Vishal\Anaconda3\lib\site-packages\cerberus\errors.py", line 510, in add
error = deepcopy(error)
File "C:\Users\D.Vishal\Anaconda3\lib\copy.py", line 180, in deepcopy
y = _reconstruct(x, memo, *rv)
File "C:\Users\D.Vishal\Anaconda3\lib\copy.py", line 280, in _reconstruct
state = deepcopy(state, memo)
File "C:\Users\D.Vishal\Anaconda3\lib\copy.py", line 150, in deepcopy
y = copier(x, memo)
File "C:\Users\D.Vishal\Anaconda3\lib\copy.py", line 240, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "C:\Users\D.Vishal\Anaconda3\lib\copy.py", line 180, in deepcopy
y = _reconstruct(x, memo, *rv)
File "C:\Users\D.Vishal\Anaconda3\lib\copy.py", line 281, in _reconstruct
if hasattr(y, '__setstate__'):
File "C:\Users\D.Vishal\Anaconda3\lib\site-packages\werkzeug\datastructures.py", line 2822, in __getattr__
return getattr(self.stream, name)
File "C:\Users\D.Vishal\Anaconda3\lib\site-packages\werkzeug\datastructures.py", line 2822, in __getattr__
return getattr(self.stream, name)
File "C:\Users\D.Vishal\Anaconda3\lib\site-packages\werkzeug\datastructures.py", line 2822, in __getattr__
return getattr(self.stream, name)
[Previous line repeated 477 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object
我不知道我是否遗漏了什么或做错了什么。任何帮助都会很棒。提前致谢。
解决方案
推荐阅读
- google-cloud-automl - Google AutoML 数据集所需的文件格式是什么?
- python - Scrapy 没有使用 extract_first() 获得干净的文本
- sql - 嵌套查询并将其结果作为别名传递给 SUM
- javascript - React JS this.props.state 不是函数?
- java - 如何在创建新用户之前保存已登录的 FirebaseUser
- javascript - 在 Axios 请求中使用 Promise
- c# - Unity Build 使用 Oculus SDK 在启动时显示黑屏
- javascript - JS创建动态generateItems不起作用
- pandas - Pandas 将列转置为行
- python - 将 Pandas 行转换为数组矩阵