千家信息网

怎么向s3cmd服务上传数据

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,本篇内容主要讲解"怎么向s3cmd服务上传数据",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么向s3cmd服务上传数据"吧!1. 基本原理操作流程:1.
千家信息网最后更新 2025年02月01日怎么向s3cmd服务上传数据

本篇内容主要讲解"怎么向s3cmd服务上传数据",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么向s3cmd服务上传数据"吧!

1. 基本原理

操作流程:
1.客户端向presign server提交上传操作请求,生成对应的presign URL
2.使用生成的presign URL构造HTTP请求,向S3服务上传数据。

2. 优缺点

优点:
1. accesskey和secretkey不会存储在客户端,避免key泄露
2. 每个presignURL对应一个keyname,在有效时间内可以任意上传和覆盖已有文件,比较灵活。
3. 服务端可以结合各种Auth系统完成客户端的认证和授权,方便集成现有业务。
4. 客户端上传下载方式灵活,拿到presignURL以后,可以通过任意支持HTTP协议的客户端进行上传下载操作。

缺点:
1. 上传和下载的交互比普通上传要多出一个步骤。
2. 文中的presign是以单次PUT方式上传,大文件不适用这个方法。

3.具体实现

安装服务端依赖

pip install botopip install flask-restful

服务端demo代码如下:

# -*- coding: utf-8 -*-import botoimport boto.s3.connectionfrom flask import Flask, requestfrom flask_restful import Resource, Apiimport res3enpoint = 's3.ceph.work' #S3服务的endpointaccess_key = '' #access_keysecret_key = '' #secret_keybucket = 'multi-upload' #上传数据存放的bucket名称class Presign_Upload(Resource):    def __init__(self):        self.s3enpoint = s3enpoint        self.access_key = access_key        self.secret_key = secret_key        self.bucket = bucket        # super(Presign_Upload,self).__init__()        self.headers = {}    def presign(self,key_name,expires_in):        conn = boto.connect_s3(                aws_access_key_id = self.access_key,                aws_secret_access_key = self.secret_key,                host = self.s3enpoint,                port = 80 ,                is_secure = False,               # uncommmnt if you are not using ssl                # calling_format = boto.s3.connection.OrdinaryCallingFormat(), #use path-style                calling_format = boto.s3.connection.SubdomainCallingFormat(), #use virtual-hosted-style                )        presigened_url = conn.generate_url(expires_in, "PUT", self.bucket, key_name,headers=self.headers)        return presigened_url    def get(self):        if not request.args.get("keyname"):            return "no keyname", 404        else:            keyname = request.args.get("keyname")        if not request.args.get("expires"):            return "no expires", 404        else:            expires = int(request.args.get("expires"))        if request.args.get("contentype"):            contentype = request.args.get("contentype")            self.headers['Content-Type'] = contentype        if request.args.get("policy"):            policy = request.args.get("policy")            self.headers['x-amz-acl'] = policy        meatadata_rule = 'x-amz-meta-'        for parm in request.args:            if re.match(meatadata_rule, parm):                self.headers[parm] = request.args.get(parm)        return {"PresignURL": self.presign(keyname, expires)}class Presign_Download(Resource):    def __init__(self):        Resource.__init__(self)        self.s3enpoint = s3enpoint        self.access_key = access_key        self.secret_key = secret_key        self.bucket = bucket        self.headers = {}    def presign(self,key_name,expires_in):        conn = boto.connect_s3(                aws_access_key_id = self.access_key,                aws_secret_access_key = self.secret_key,                host = self.s3enpoint,                port = 80 ,                is_secure = False,               # uncommmnt if you are not using ssl                # calling_format = boto.s3.connection.OrdinaryCallingFormat(), #use path-style                calling_format = boto.s3.connection.SubdomainCallingFormat(), #use virtual-hosted-style                )        presigened_url = conn.generate_url(expires_in, "GET", self.bucket, key_name)        return presigened_url    def get(self):        if not request.args.get("keyname"):            return "no keyname", 400        else:            keyname = request.args.get("keyname")        if not request.args.get("expires"):            return "no expires", 400        else:            expires = int(request.args.get("expires"))        return {"PresignURL": self.presign(keyname, expires)}app = Flask(__name__)api = Api(app)api.add_resource(Presign_Upload, '/upload')api.add_resource(Presign_Download, '/download')if __name__ == '__main__':    app.run(debug=True)

安装客户端依赖

pip install requests

客户端demo代码如下:

# -*- coding: utf-8 -*-import requestsimport jsonclass Presign_client():    def __init__(self, server_url):        self.server_url = server_url        self.headers = {}    def get_upload_presignURL(self, keyname, expires, policy=None, contentype=None, metadata=None):        base_url_ = "{server_url}/upload?keyname={keyname}&expires={expires}".format(server_url=server_url,keyname=keyname,expires=expires)        if contentype:            self.headers['Content-Type'] = contentype            base_url_ = "{base_url_}&contentype={contentype}".format(base_url_=base_url_,contentype=contentype)        if policy:            self.headers['x-amz-acl'] = policy            base_url_ = "{base_url_}&policy={policy}".format(base_url_=base_url_,policy=policy)        if metadata:            for k in metadata:                metadata_key = k                metadata_value = metadata[k]                self.headers[metadata_key] = str(metadata_value)                base_url_ = "{base_url_}&{metadata_key}={metadata_value}".format(base_url_=base_url_,metadata_key=str(metadata_key),metadata_value=metadata_value)        res = requests.get(base_url_)        return json.loads(res.content)['PresignURL']    def upload_file(self,SignURL,filepath):        with open(filepath) as fh:            mydata = fh.read()            response = requests.put(SignURL,data=mydata,headers=self.headers)            if response.status_code == 200:                print "Upload {} Successful!".format(filepath)            else:                print "Failed! status_code={}".format(response.status_code)    def get_download_presignURL(self, keyname, expires):        base_url_ = "{server_url}/download?keyname={keyname}&expires={expires}".format(server_url=server_url,keyname=keyname,expires=expires)        response = requests.get(base_url_)        return json.loads(response.content)['PresignURL']    def download_file(self,SignURL,filepath):        response = requests.get(SignURL)        if response.status_code == 200:            with open(filepath,'wb') as fh:                fh.write(response.content)            print "Download {} Successful!".format(filepath)        else:            print "Failed! status_code={}".format(response.status_code)server_url = 'http://localhost:5000' #填服务端地址metadata ={'x-amz-meta-abc':333,'x-amz-meta-key':'value'} #上传文件的自定义metadatacontentype = 'abc/pdf' #设置上传文件的Content-Typepolicy = 'public-read' #设置上传文件的ACLexpires = 300 #设置presignURL有效时长,单位秒file_path = '/Users/demouser/Downloads/1.pdf' #上传文件路径save_path = '/tmp/download.pdf' #下载文件存储路径keyname = 'upload.pdf' #上传文件的名称,对应object的keynameclient = Presign_client(server_url)#生成上传presignURL,并上传文件Upload_SignURL = client.get_upload_presignURL(keyname=keyname, expires=expires, policy=policy, contentype=contentype, metadata=metadata)client.upload_file(Upload_SignURL,file_path)#下载presignURL,并下载文件Download_SignURL = client.get_download_presignURL(keyname=keyname, expires=expires)client.download_file(Download_SignURL,save_path)

到此,相信大家对"怎么向s3cmd服务上传数据"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0