如何确认上传 "directly" 到 S3,而不先通过后端服务器代理? (Python 烧瓶示例)
How to confirm that an upload goes "directly" to S3, without proxying through the backend server first? (Python Flask example)
我很好奇如何区分使用 Fineuploader 将文件上传到 S3(使用首先通过后端代理文件的传统方法与从客户端直接上传)之间的区别。
这是我从 Fineuploader Github 检索到的后端代码,并根据我的用例进行了微调。
#!/usr/bin/env python
#
# app.py
#
# by: Mark Feltner
#
# Server-side S3 upload example for Fine Uploader
#
# Features:
# * Upload to S3
# * Delete from S3
# * Sign Policy documents (simple uploads) and REST requests (chunked/multipart)
# uploads
# * non-CORS environment
import base64, hmac, hashlib, os, sys
from flask import (Flask, abort, json, jsonify, make_response, render_template, request)
from boto.s3.connection import Key, S3Connection
AWS_CLIENT_SECRET_KEY = '********************************'
AWS_SERVER_PUBLIC_KEY = '************************'
AWS_SERVER_SECRET_KEY = '*********************************'
AWS_EXPECTED_BUCKET = 'mybucket'
AWS_MAX_SIZE = 1500000000
app = Flask(__name__, template_folder='static', static_url_path='/static')
app.config.from_object(__name__)
app.debug = True
def sign_policy(policy):
""" Sign and return the policy document for a simple upload.
http://aws.amazon.com/articles/1434/#signyours3postform """
signed_policy = base64.b64encode(policy)
signature = base64.b64encode(hmac.new(
app.config.get('AWS_CLIENT_SECRET_KEY'), signed_policy, hashlib.sha1).
digest())
return {'policy': signed_policy, 'signature': signature}
def sign_headers(headers):
""" Sign and return the headers for a chunked upload. """
return {
'signature': base64.b64encode(hmac.new(
app.config.get('AWS_CLIENT_SECRET_KEY'), headers, hashlib.sha1).
digest())
}
@app.route("/s3/sign", methods=['POST'])
def s3_signature():
""" Route for signing the policy document or REST headers. """
request_payload = request.get_json()
if request_payload.get('headers'):
response_data = sign_headers(request_payload['headers'])
else:
response_data = sign_policy(request.data)
return jsonify(response_data)
@app.route("/s3handler/<key>", methods=['POST', 'DELETE'])
def s3_delete(key=None):
""" Route for deleting files off S3. Uses the SDK. """
try:
s3 = S3Connection(app.config.get("AWS_SERVER_PUBLIC_KEY"),
app.config.get("AWS_SERVER_SECRET_KEY"))
request_payload = request.values
bucket_name = request_payload.get('bucket')
key_name = request_payload.get('key')
aws_bucket = s3.get_bucket(bucket_name, validate=False)
aws_key = Key(aws_bucket, key_name)
aws_key.delete()
return make_response('', 200)
except ImportError:
abort(500)
@app.route("/s3/success", methods=['GET', 'POST'])
def s3_success():
""" Success redirect endpoint for <=IE9. """
return make_response('', 200)
@app.route("/")
def index():
return render_template("index.html")
def main(argv=None):
app.run('0.0.0.0')
return 0 # success
if __name__ == '__main__':
status = main()
sys.exit(status)
在客户端,减去 UI 代码,我有这个脚本来处理客户端的请求
<script>
var uploader = new qq.s3.FineUploader({
debug: true,
element: document.getElementById('fine-uploader'),
request: {
endpoint: 'mybucket.s3.amazonaws.com',
accessKey: '***************'
},
signature: {
endpoint: '/s3/sign'
},
uploadSuccess: {
endpoint: '/s3/success'
},
iframeSupport: {
localBlankPagePath: '/success.html'
},
retry: {
enableAuto: true // defaults to false
},
chunking: {
enabled: true
},
deleteFile: {
enabled: true,
endpoint: '/s3handler'
}
});
</script>
这对我有用。上传的文件出现在我的 S3 存储桶中。我假设这是通过仅要求后端签署策略文件然后继续上传到 S3 "directly"。这个对吗?如果文件必须通过后端而不是直接上传,会有什么不同的做法?
经过 Ray Nicholus 的澄清,直接上传到 S3 或替代服务器的区别在于 Fineuploader 客户端方法
直接上传到S3:qq.s3.FineUploader
上传到您选择的服务器:qq.FineUploader
我很好奇如何区分使用 Fineuploader 将文件上传到 S3(使用首先通过后端代理文件的传统方法与从客户端直接上传)之间的区别。 这是我从 Fineuploader Github 检索到的后端代码,并根据我的用例进行了微调。
#!/usr/bin/env python
#
# app.py
#
# by: Mark Feltner
#
# Server-side S3 upload example for Fine Uploader
#
# Features:
# * Upload to S3
# * Delete from S3
# * Sign Policy documents (simple uploads) and REST requests (chunked/multipart)
# uploads
# * non-CORS environment
import base64, hmac, hashlib, os, sys
from flask import (Flask, abort, json, jsonify, make_response, render_template, request)
from boto.s3.connection import Key, S3Connection
AWS_CLIENT_SECRET_KEY = '********************************'
AWS_SERVER_PUBLIC_KEY = '************************'
AWS_SERVER_SECRET_KEY = '*********************************'
AWS_EXPECTED_BUCKET = 'mybucket'
AWS_MAX_SIZE = 1500000000
app = Flask(__name__, template_folder='static', static_url_path='/static')
app.config.from_object(__name__)
app.debug = True
def sign_policy(policy):
""" Sign and return the policy document for a simple upload.
http://aws.amazon.com/articles/1434/#signyours3postform """
signed_policy = base64.b64encode(policy)
signature = base64.b64encode(hmac.new(
app.config.get('AWS_CLIENT_SECRET_KEY'), signed_policy, hashlib.sha1).
digest())
return {'policy': signed_policy, 'signature': signature}
def sign_headers(headers):
""" Sign and return the headers for a chunked upload. """
return {
'signature': base64.b64encode(hmac.new(
app.config.get('AWS_CLIENT_SECRET_KEY'), headers, hashlib.sha1).
digest())
}
@app.route("/s3/sign", methods=['POST'])
def s3_signature():
""" Route for signing the policy document or REST headers. """
request_payload = request.get_json()
if request_payload.get('headers'):
response_data = sign_headers(request_payload['headers'])
else:
response_data = sign_policy(request.data)
return jsonify(response_data)
@app.route("/s3handler/<key>", methods=['POST', 'DELETE'])
def s3_delete(key=None):
""" Route for deleting files off S3. Uses the SDK. """
try:
s3 = S3Connection(app.config.get("AWS_SERVER_PUBLIC_KEY"),
app.config.get("AWS_SERVER_SECRET_KEY"))
request_payload = request.values
bucket_name = request_payload.get('bucket')
key_name = request_payload.get('key')
aws_bucket = s3.get_bucket(bucket_name, validate=False)
aws_key = Key(aws_bucket, key_name)
aws_key.delete()
return make_response('', 200)
except ImportError:
abort(500)
@app.route("/s3/success", methods=['GET', 'POST'])
def s3_success():
""" Success redirect endpoint for <=IE9. """
return make_response('', 200)
@app.route("/")
def index():
return render_template("index.html")
def main(argv=None):
app.run('0.0.0.0')
return 0 # success
if __name__ == '__main__':
status = main()
sys.exit(status)
在客户端,减去 UI 代码,我有这个脚本来处理客户端的请求
<script>
var uploader = new qq.s3.FineUploader({
debug: true,
element: document.getElementById('fine-uploader'),
request: {
endpoint: 'mybucket.s3.amazonaws.com',
accessKey: '***************'
},
signature: {
endpoint: '/s3/sign'
},
uploadSuccess: {
endpoint: '/s3/success'
},
iframeSupport: {
localBlankPagePath: '/success.html'
},
retry: {
enableAuto: true // defaults to false
},
chunking: {
enabled: true
},
deleteFile: {
enabled: true,
endpoint: '/s3handler'
}
});
</script>
这对我有用。上传的文件出现在我的 S3 存储桶中。我假设这是通过仅要求后端签署策略文件然后继续上传到 S3 "directly"。这个对吗?如果文件必须通过后端而不是直接上传,会有什么不同的做法?
经过 Ray Nicholus 的澄清,直接上传到 S3 或替代服务器的区别在于 Fineuploader 客户端方法
直接上传到S3:qq.s3.FineUploader
上传到您选择的服务器:qq.FineUploader