flask開發restful api系列(4)--七牛圖片服務

  上一章咱們講到如何利用alembic來更新數據庫,這章,咱們講如何經過七牛服務來存儲圖片。python

  像咱們大多數公司同樣,公司資金比較少,若是本身開發圖片服務器,代價太大;若是咱們用本身的網站服務器來保存圖片,極可能會把帶寬阻塞住。所以,一款優秀的第三方圖片服務變得很是重要。七牛就是這麼一款,上傳代碼簡單,能夠在線編輯,簡單的變換url,能夠獲得圖片的不一樣效果。關鍵是,它是在必定限額內是免費的,只要經過認證,基本都夠用了。咱們公司如今包括app,網站全部圖片都放在七牛,一直用的很好,一分錢也沒有花。redis

  好了,閒話少說,本身先申請一個七牛帳號,登陸進去,能夠本身先玩一下,直接上傳一個圖片。數據庫

  

  這就是我七牛帳號裏面的圖片,咱們點擊內容上傳,編程

速度不是通常的快呀,作技術出生的CEO果真就是不一樣,點擊"關閉",而後打開外鏈,看看效果吧。http://7xk6rc.com1.z0.glb.clouddn.com/2016-05-04%2015-06-21%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE.png 這是我剛纔上傳的,你能夠打開看看,是否是很簡單?就是這麼簡單,而後咱們用編程的方式上傳,僅此而已。json

好了,下面上python上傳代碼,首先,按照文檔,先安裝一下qiniu模塊。api

pip install qiniu

安裝好之後,先隨便寫一個python上傳代碼,看看咱們實際過程當中須要提供什麼。服務器

# coding:utf-8
from qiniu import Auth, put_file, etag, urlsafe_base64_encode

access_key = 'access_key'
secret_key = 'secret_key'

q = Auth(access_key=access_key, secret_key=secret_key)

bucket_name = 'dameinv'

key = 'my-test-picture.png'

token = q.upload_token(bucket_name, key, 3600)

print token

localfile = './my-test.png'


ret, info = put_file(token, key, localfile)

print ret
print info

看看打印結果session

hP7WNicFRHPu2Bd24MaLj5VvmElXYJbRCoZfrVs6:Fi7LRD1ufxI6GaoRRUeX9ncRk0g=:eyJzY29wZSI6ImRhbWVpbnY6bXktdGVzdC1waWN0dXJlLnBuZyIsImRlYWRsaW5lIjoxNDYyMzUwMTk3fQ==
{u'hash': u'FvSC6ud6RL3jLmARbabBuzQttbNO', u'key': u'my-test-picture.png'}
exception:None, status_code:200, _ResponseInfo__response:<Response [200]>, text_body:{"hash":"FvSC6ud6RL3jLmARbabBuzQttbNO","key":"my-test-picture.png"}, req_id:pSEAAMKvVqF7TEsU, x_log:s.ph;s.put.tw;s.put.tr;s.put.tw;s.put.tr;s.ph;s.put.tw;s.put.tr;s.ph;PFDS;PFDS:1;PFDS:2;rs18_6.sel/not found;rdb.g/no such key;DBD/404;v4.get:1/Document not found;rs19_6.ups;qtbl.ups:2;mc.s;RS:2;rs.put:4;rs-upload.putFile:7;UP:9

Process finished with exit code 0

好了,看看實際在七牛的效果。app

http://7xk6rc.com1.z0.glb.clouddn.com/my-test-picture.pngpost

打開看看吧,這就是實際效果。

下面咱們就來逐個分析一下代碼,

首先,access_key和secret_key就是你的'我的面板'===>'密鑰管理'裏面的2個key,直接複製過來就能夠了,這個key很重要,千萬不能泄露哦。

其次,q = Auth(access_key=access_key, secret_key=secret_key)新建一個qiniu上傳對象;bucket_name就是你的空間名,個人空間名是「dameimv」,能夠建多個空間,看看我全部空間名;我用的最上面的那個;key,其實這個命名有點問題的,其實應該叫路徑,至於爲何七牛文檔中叫它key,就不得而知了;而後咱們利用bucket_name和key,返回一個token,這個token之後就是咱們主要返回給客戶端的,第三個參數,就是它過時時間,我這邊就隨便設置1個小時過時。

最後,就是上傳,其實之後,這是客戶端的事,咱們服務器端只要提供token和key就能夠了,客戶端上傳成功之後,直接告訴咱們路徑便可。其實就是一個put_file而已。

看看返回結果,我我的就是看info的status_code,若是是200就表明上傳成功。

是否是很是簡單!好了,在此基礎上,咱們寫接口吧。首先,我一般的作法是,服務器端提供token和key的接口,客戶端拿到之後,本身上傳圖片,上傳成功了,再把整個url給我,這樣,服務器不會浪費任何帶寬資源,並且也不會中途出錯,致使其餘問題。即便客戶端出錯,它能夠本身從新上傳,或者根本不上傳,服務器端不須要存儲任何數據,也不會出現其餘意外。

import uuid
from qiniu import Auth, put_file, etag, urlsafe_base64_encode
access_key = 'access_key'
secret_key = 'secret_key'
q = Auth(access_key=access_key, secret_key=secret_key)
bucket_name = 'dameinv'


@app.route('/get-qiniu-token')
def get_qiniu_token():
    key = uuid.uuid4()
    token = q.upload_token(bucket_name, key, 3600)
    return jsonify({'code': 1, 'key': key, 'token': token})


@app.route('/set-head-picture', methods=['POST'])
@login_check
def set_head_picture():
    head_picture = request.get_json().get('head_picture')
    user = g.current_user
    user.head_picture = head_picture
    try:
        db_session.commit()
    except Exception as e:
        print e
        db_session.rollback()
        return jsonify({'code': 0, 'message': '未能成功上傳'})
    redis_store.hset('user:%s' % user.phone_number, 'head_picture', head_picture)
    return jsonify({'code': 1, 'message': '成功上傳'})

咱們在原來的view.py中添加如上代碼,第一個get_qiniu_token是獲取七牛的token和key,這邊的key爲了保持惟一,使用uuid,其實有2種方案,第一,你能夠用這uuid,第二,你可使用http://base_url/phone_number/time_stamp 這樣的方式,其實我更傾向於第二種,這樣,你就能夠看到在這個用戶下,有多少它上傳的東西,便於直接統計。

整個上傳代碼就這樣,照例,咱們在client.py文件下,模擬一下客戶端操做,看看有沒有問題。

# coding:utf-8
import requests
import json
from qiniu import put_file


class APITest(object):
    def __init__(self, base_url):
        self.base_url = base_url
        self.headers = {}
        self.token = None
        self.qiniu_token = None
        self.qiniu_key = None
        self.qiniu_base_url = 'http://7xk6rc.com1.z0.glb.clouddn.com/'

    def login(self, phone_number, password, path='/login'):
        payload = {'phone_number': phone_number, 'password': password}
        self.headers = {'content-type': 'application/json'}
        response = requests.post(url=self.base_url + path, data=json.dumps(payload), headers=self.headers)
        response_data = json.loads(response.content)
        self.token = response_data.get('token')
        return response_data

    def user(self, path='/user'):
        self.headers = {'token': self.token}
        response = requests.get(url=self.base_url + path, headers=self.headers)
        response_data = json.loads(response.content)
        return response_data

    def logout(self, path='/logout'):
        self.headers = {'token': self.token}
        response = requests.get(url=self.base_url + path, headers=self.headers)
        response_data = json.loads(response.content)
        return response_data

    def get_qiniu_token(self, path='/get-qiniu-token'):
        response = requests.get(url=self.base_url + path)
        response_data = json.loads(response.content)
        self.qiniu_token = response_data.get('token')
        self.qiniu_key = response_data.get('key')
        if self.qiniu_token and self.qiniu_key:
            print '成功獲取qiniu_token和qiniu_key,分別爲%s和%s' % (self.qiniu_token.encode('utf-8'), self.qiniu_key.encode('utf-8'))
            localfile = '/home/yudahai/PycharmProjects/blog01/app/my-test.png'
            ret, info = put_file(self.qiniu_token, self.qiniu_key, localfile)
            print info.status_code
            if info.status_code == 200:
                print '上傳成功'
                self.head_picture = self.qiniu_base_url + self.qiniu_key
                print '其url爲:' + self.head_picture.encode('utf-8')
            else:
                print '上傳失敗'
        return response_data

    def set_head_picture(self, path='/set-head-picture'):
        payload = {'head_picture': self.head_picture}
        self.headers = {'token': self.token, 'content-type': 'application/json'}
        response = requests.post(url=self.base_url + path, data=json.dumps(payload), headers=self.headers)
        response_data = json.loads(response.content)
        print response_data.get('message')
        return response_data

if __name__ == '__main__':
    api = APITest('http://127.0.0.1:5001')
    api.login('13565208554', '123456')
    api.get_qiniu_token()
    api.set_head_picture()
    api.logout()

運行一下,看看結果吧。

1 成功獲取qiniu_token和qiniu_key,分別爲hP7WNicFRHPu2Bd24MaLj5VvmElXYJbRCoZfrVs6:WZLWPx0bZ04KjSU0zRYKrPitWoE=:eyJzY29wZSI6ImRhbWVpbnY6YjU2NGJlOTAtMjM2ZS00YjQzLWE1M2UtZGRjMThlNTJmYmQxIiwiZGVhZGxpbmUiOjE0NjIzNTYwOTJ9和b564be90-236e-4b43-a53e-ddc18e52fbd1
2 200
3 上傳成功
4 其url爲:http://7xk6rc.com1.z0.glb.clouddn.com/b564be90-236e-4b43-a53e-ddc18e52fbd1
5 成功上傳

已經上傳成功了,看看頭像結果

>>> from app.model import *
>>> user = User.query.filter_by('13565208554').first()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: filter_by() takes exactly 1 argument (2 given)
>>> user = User.query.filter_by(phone_number='13565208554').first()
>>> user.head_picture
u'http://7xk6rc.com1.z0.glb.clouddn.com/b564be90-236e-4b43-a53e-ddc18e52fbd1'

看,已經成功了。

之後幾乎全部的圖片均可以這麼處理,在客戶端須要圖片以前,讓他們先訪問get-qiniu-token接口,拿到token和key,客戶端根據token和key來上傳本身的東西。每上傳一次,就訪問一次get-qiniu-token接口。

 好了,這就是簡單的七牛上傳圖片介紹,詳細的說明,他們都有文檔,文檔作的很是清晰。下一章,咱們利用容聯雲通信來完成註冊過程,也很是簡單。

相關文章
相關標籤/搜索