国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

Flask/MongoDB搭建簡易圖片服務器

來源:懂視網 責編:小采 時間:2020-11-09 13:18:46
文檔

Flask/MongoDB搭建簡易圖片服務器

Flask/MongoDB搭建簡易圖片服務器:前期準備 通過 pip 或 easy_install 安裝了 pymongo 之后, 就能通過 Python 調教 mongodb 了. 接著安裝個 flask 用來當 web 服務器. 當然 mongo 也是得安裝的. 對于 Ubuntu 用戶, 特別是使用 Server 12.04 的同學, 安裝最新版要略費些周折
推薦度:
導讀Flask/MongoDB搭建簡易圖片服務器:前期準備 通過 pip 或 easy_install 安裝了 pymongo 之后, 就能通過 Python 調教 mongodb 了. 接著安裝個 flask 用來當 web 服務器. 當然 mongo 也是得安裝的. 對于 Ubuntu 用戶, 特別是使用 Server 12.04 的同學, 安裝最新版要略費些周折

前期準備 通過 pip 或 easy_install 安裝了 pymongo 之后, 就能通過 Python 調教 mongodb 了. 接著安裝個 flask 用來當 web 服務器. 當然 mongo 也是得安裝的. 對于 Ubuntu 用戶, 特別是使用 Server 12.04 的同學, 安裝最新版要略費些周折, 具體說是 sudoapt

前期準備

通過 pip 或 easy_install 安裝了 pymongo 之后, 就能通過 Python 調教 mongodb 了.
接著安裝個 flask 用來當 web 服務器.
當然 mongo 也是得安裝的. 對于 Ubuntu 用戶, 特別是使用 Server 12.04 的同學, 安裝最新版要略費些周折, 具體說是

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
sudo apt-get update
sudo apt-get install mongodb-10gen

如果你跟我一樣覺得讓通過上傳文件名的后綴判別用戶上傳的什么文件完全是捏著山藥當小黃瓜一樣欺騙自己, 那么最好還準備個 Pillow 庫

pip install Pillow

或 (更適合 Windows 用戶)

easy_install Pillow

正片

Flask 文件上傳

Flask 官網上那個例子居然分了兩截讓人無從吐槽. 這里先弄個最簡單的, 無論什么文件都先弄上來

import flask

app = flask.Flask(__name__)
app.debug = True

@app.route('/upload', methods=['POST'])
def upload():
f = flask.request.files['uploaded_file']
print f.read()
return flask.redirect('/')

@app.route('/')
def index():
return '''




'''

if __name__ == '__main__':
app.run(port=7777)

  • 注: 在 upload 函數中, 使用 flask.request.files[KEY] 獲取上傳文件對象, KEY 為頁面 form 中 input 的 name 值
  • 因為是在后臺輸出內容, 所以測試最好拿純文本文件來測.

    保存到 mongodb

    如果不那么講究的話, 最快速基本的存儲方案里只需要

    import pymongo
    import bson.binary
    from cStringIO import StringIO

    app = flask.Flask(__name__)
    app.debug = True
    db = pymongo.MongoClient('localhost', 27017).test

    def save_file(f):
    content = StringIO(f.read())
    db.files.save(dict(
    content=bson.binary.Binary(content.getvalue()),
    ))

    @app.route('/upload', methods=['POST'])
    def upload():
    f = flask.request.files['uploaded_file']
    save_file(f)
    return flask.redirect('/')

    把內容塞進一個 bson.binary.Binary 對象, 再把它扔進 mongodb 就可以了.
    現在試試再上傳個什么文件, 在 mongo shell 中通過

    db.files.find()

    就能看到了. 不過 content 這個域幾乎肉眼無法分辨出什么東西, 即使是純文本文件, mongo 也會顯示為 Base64 編碼.

    提供文件訪問

    給定存進數據庫的文件的 ID (作為 URI 的一部分), 返回給瀏覽器其文件內容, 如下

    def save_file(f):
    content = StringIO(f.read())
    c = dict(content=bson.binary.Binary(content.getvalue()))
    db.files.save(c)
    return c['_id']

    @app.route('/f/')
    def serve_file(fid):
    f = db.files.find_one(bson.objectid.ObjectId(fid))
    return f['content']

    @app.route('/upload', methods=['POST'])
    def upload():
    f = flask.request.files['uploaded_file']
    fid = save_file(f)
    return flask.redirect('/f/' + str(fid))

    上傳文件之后, upload 函數會跳轉到對應的文件瀏覽頁. 這樣一來, 文本文件內容就可以正常預覽了, 如果不是那么挑剔換行符跟連續空格都被瀏覽器吃掉的話.

    當找不到文件時

    有兩種情況, 其一, 數據庫 ID 格式就不對, 這時 pymongo 會拋異常 bson.errors.InvalidId; 其二, 找不到對象 (!), 這時 pymongo 會返回 None.
    簡單起見就這樣處理了

    @app.route('/f/')
    def serve_file(fid):
    import bson.errors
    try:
    f = db.files.find_one(bson.objectid.ObjectId(fid))
    if f is None:
    raise bson.errors.InvalidId()
    return f['content']
    except bson.errors.InvalidId:
    flask.abort(404)

    正確的 MIME

    從現在開始要對上傳的文件嚴格把關了, 文本文件, 狗與剪刀等皆不能上傳.
    判斷圖片文件之前說了我們動真格用 Pillow

    from PIL import Image

    allow_formats = set(['jpeg', 'png', 'gif'])

    def save_file(f):
    content = StringIO(f.read())
    try:
    mime = Image.open(content).format.lower()
    if mime not in allow_formats:
    raise IOError()
    except IOError:
    flask.abort(400)
    c = dict(content=bson.binary.Binary(content.getvalue()))
    db.files.save(c)
    return c['_id']

    然后試試上傳文本文件肯定虛, 傳圖片文件才能正常進行. 不對, 也不正常, 因為傳完跳轉之后, 服務器并沒有給出正確的 mimetype, 所以仍然以預覽文本的方式預覽了一坨二進制亂碼.
    要解決這個問題, 得把 MIME 一并存到數據庫里面去; 并且, 在給出文件時也正確地傳輸 mimetype

    def save_file(f):
    content = StringIO(f.read())
    try:
    mime = Image.open(content).format.lower()
    if mime not in allow_formats:
    raise IOError()
    except IOError:
    flask.abort(400)
    c = dict(content=bson.binary.Binary(content.getvalue()), mime=mime)
    db.files.save(c)
    return c['_id']

    @app.route('/f/')
    def serve_file(fid):
    try:
    f = db.files.find_one(bson.objectid.ObjectId(fid))
    if f is None:
    raise bson.errors.InvalidId()
    return flask.Response(f['content'], mimetype='image/' + f['mime'])
    except bson.errors.InvalidId:
    flask.abort(404)

    當然這樣的話原來存進去的東西可沒有 mime 這個屬性, 所以最好先去 mongo shell 用 db.files.drop() 清掉原來的數據.

    根據上傳時間給出 NOT MODIFIED

    利用 HTTP 304 NOT MODIFIED 可以盡可能壓榨與利用瀏覽器緩存和節省帶寬. 這需要三個操作
  • 記錄文件最后上傳的時間
  • 當瀏覽器請求這個文件時, 向請求頭里塞一個時間戳字符串
  • 當瀏覽器請求文件時, 從請求頭中嘗試獲取這個時間戳, 如果與文件的時間戳一致, 就直接 304
  • 體現為代碼是

    import datetime

    def save_file(f):
    content = StringIO(f.read())
    try:
    mime = Image.open(content).format.lower()
    if mime not in allow_formats:
    raise IOError()
    except IOError:
    flask.abort(400)
    c = dict(
    content=bson.binary.Binary(content.getvalue()),
    mime=mime,
    time=datetime.datetime.utcnow(),
    )
    db.files.save(c)
    return c['_id']

    @app.route('/f/')
    def serve_file(fid):
    try:
    f = db.files.find_one(bson.objectid.ObjectId(fid))
    if f is None:
    raise bson.errors.InvalidId()
    if flask.request.headers.get('If-Modified-Since') == f['time'].ctime():
    return flask.Response(status=304)
    resp = flask.Response(f['content'], mimetype='image/' + f['mime'])
    resp.headers['Last-Modified'] = f['time'].ctime()
    return resp
    except bson.errors.InvalidId:
    flask.abort(404)

    然后, 得弄個腳本把數據庫里面已經有的圖片給加上時間戳.
    順帶吐個槽, 其實 NoSQL DB 在這種環境下根本體現不出任何優勢, 用起來跟 RDB 幾乎沒兩樣.

    利用 SHA-1 排重

    與冰箱里的可樂不同, 大部分情況下你肯定不希望數據庫里面出現一大波完全一樣的圖片. 圖片, 連同其 EXIFF 之類的數據信息, 在數據庫中應該是惟一的, 這時使用略強一點的散列技術來檢測是再合適不過了.
    達到這個目的最簡單的就是建立一個 SHA-1 惟一索引, 這樣數據庫就會阻止相同的東西被放進去.
    在 MongoDB 中表中建立惟一索引, 執行 (Mongo 控制臺中)

    db.files.ensureIndex({sha1: 1}, {unique: true})

    如果你的庫中有多條記錄的話, MongoDB 會給報個錯. 這看起來很和諧無害的索引操作被告知數據庫中有重復的取值 null (實際上目前數據庫里已有的條目根本沒有這個屬性). 與一般的 RDB 不同的是, MongoDB 規定 null, 或不存在的屬性值也是一種相同的屬性值, 所以這些幽靈屬性會導致惟一索引無法建立.
    解決方案有三個
  • 刪掉現在所有的數據 (一定是測試數據庫才用這種不負責任的方式吧!)
  • 建立一個 sparse 索引, 這個索引不要求幽靈屬性惟一, 不過出現多個 null 值還是會判定重復 (不管現有數據的話可以這么搞)
  • 寫個腳本跑一次數據庫, 把所有已經存入的數據翻出來, 重新計算 SHA-1, 再存進去
  • 具體做法隨意. 假定現在這個問題已經搞定了, 索引也弄好了, 那么剩是 Python 代碼的事情了.

    import hashlib

    def save_file(f):
    content = StringIO(f.read())
    try:
    mime = Image.open(content).format.lower()
    if mime not in allow_formats:
    raise IOError()
    except IOError:
    flask.abort(400)

    sha1 = hashlib.sha1(content.getvalue()).hexdigest()
    c = dict(
    content=bson.binary.Binary(content.getvalue()),
    mime=mime,
    time=datetime.datetime.utcnow(),
    sha1=sha1,
    )
    try:
    db.files.save(c)
    except pymongo.errors.DuplicateKeyError:
    pass
    return c['_id']

    在上傳文件這一環就沒問題了. 不過, 按照上面這個邏輯, 如果上傳了一個已經存在的文件, 返回 c['_id'] 將會是一個不存在的數據 ID. 修正這個問題, 最好是返回 sha1, 另外, 在訪問文件時, 相應地修改為用文件 SHA-1 訪問, 而不是用 ID.
    最后修改的結果及本篇完整源代碼如下

    import hashlib
    import datetime
    import flask
    import pymongo
    import bson.binary
    import bson.objectid
    import bson.errors
    from cStringIO import StringIO
    from PIL import Image

    app = flask.Flask(__name__)
    app.debug = True
    db = pymongo.MongoClient('localhost', 27017).test
    allow_formats = set(['jpeg', 'png', 'gif'])

    def save_file(f):
    content = StringIO(f.read())
    try:
    mime = Image.open(content).format.lower()
    if mime not in allow_formats:
    raise IOError()
    except IOError:
    flask.abort(400)

    sha1 = hashlib.sha1(content.getvalue()).hexdigest()
    c = dict(
    content=bson.binary.Binary(content.getvalue()),
    mime=mime,
    time=datetime.datetime.utcnow(),
    sha1=sha1,
    )
    try:
    db.files.save(c)
    except pymongo.errors.DuplicateKeyError:
    pass
    return sha1

    @app.route('/f/')
    def serve_file(sha1):
    try:
    f = db.files.find_one({'sha1': sha1})
    if f is None:
    raise bson.errors.InvalidId()
    if flask.request.headers.get('If-Modified-Since') == f['time'].ctime():
    return flask.Response(status=304)
    resp = flask.Response(f['content'], mimetype='image/' + f['mime'])
    resp.headers['Last-Modified'] = f['time'].ctime()
    return resp
    except bson.errors.InvalidId:
    flask.abort(404)

    @app.route('/upload', methods=['POST'])
    def upload():
    f = flask.request.files['uploaded_file']
    sha1 = save_file(f)
    return flask.redirect('/f/' + str(sha1))

    @app.route('/')
    def index():
    return '''




    '''

    if __name__ == '__main__':
    app.run(port=7777)

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    Flask/MongoDB搭建簡易圖片服務器

    Flask/MongoDB搭建簡易圖片服務器:前期準備 通過 pip 或 easy_install 安裝了 pymongo 之后, 就能通過 Python 調教 mongodb 了. 接著安裝個 flask 用來當 web 服務器. 當然 mongo 也是得安裝的. 對于 Ubuntu 用戶, 特別是使用 Server 12.04 的同學, 安裝最新版要略費些周折
    推薦度:
    標簽: 圖片 簡易 服務器
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产精品视频久久久久 | 亚洲欧美日韩中文无线码 | 99久久精品免费看国产 | 91精品国产亚一区二区三区 | 在线亚洲精品 | 亚洲黄色一区二区 | 中文字幕美日韩在线高清 | 国内精品一区二区三区 | 911香蕉| 在线观看免费精品国产 | 欧美色第一页 | 久久国产经典 | 国产精品免费在线播放 | 欧州人曾交 | 欧美亚洲另类在线观看 | 国产精品视频观看 | 国产日韩欧美在线观看不卡 | 午夜精品一区二区三区在线视 | 欧美精品久久久久久久久大尺度 | 亚洲一区二区精品视频 | 在线 v亚洲 v欧美v 专区 | 国产精品免费精品自在线观看 | 精品久久综合一区二区 | 欧美极品视频 | 欧美亚洲综合激情在线 | 人人干人人爽 | 日韩精品一区二区三区 在线观看 | 国产一区二区三区高清 | 亚洲一区二区在线免费观看 | 日韩视频在线免费观看 | 欧美在线视频观看 | 欧美在线免费 | 国内精品1区1区3区4区 | 亚洲视频在线视频 | 亚洲视频在线播放 | av毛片免费看 | 亚洲精品高清在线观看 | 国产91在线播放中文 | 欧美精品第一页 | 国产成人精品免费视频大全五级 | 国产 日韩 欧美 在线 |