Python存取圖片至服務器數據庫中

前言

由於項目需求,需要將識別的人臉圖片存儲到服務器的數據庫中,經過了解得知目前業界存儲圖片主要有兩種方式:

  1. 圖片存儲在磁盤上,即服務器文件系統中,數據庫字段中保存的是圖片的路徑。
  2. 圖片以二進制形式直接存儲到數據庫中(一般來說數據庫會提供一個二進制字段來存儲二進制數據。比如mysql中blob類型,容量64K或mediumblob類型,容量16M,longblob類型,容量4G)

對於兩種方式各自的優缺點可以看這篇文章——>關於圖片或者文件在數據庫的存儲方式歸納
總而言之:
1.圖片以二進制形式存儲在數據庫

優點:
備份的時候方便,直接備份數據庫,圖片也跟着備份。換句話說,遷移環境的時候是方便。而圖片放在磁盤上的話,數據庫中存儲的只是圖片路徑。備份數據庫後,磁盤上的圖片也要跟着備份纔行。

缺點:
圖片儘量不要存儲在數據庫中(是指不要二進制形式保存到字段,而只保存圖片的路徑)。這樣的大字段數據會加重數據庫的負擔,拖慢數據庫。在大併發訪問的情況下很重要。

2.數據庫中保存圖片路徑

優點:
數據庫中保存的是圖片路徑的話,在web開發環境下,有個好處就是可以使用cdn加速(CDN優勢及何時選擇使用CDN)。
數據庫字段中保存的是類似於這樣子的”images/2020/12/15/ 1343287394783.jpg”。原來上傳的圖片文件名稱會重新命名保存,比如按照時間戳來生成,這樣子是爲了避免文件名重複,網站的併發訪問量越大,目錄的生成分得越細越好。

缺點:
數據遷移不夠方便,操作系統對單個目錄的文件數量是有限制的。當文件數量很多的時候。從目錄中獲取文件的速度就會越來越慢。所以爲了保持速度,需要使用固定規則將圖片分散到多個目錄中去。

因此可以根據具體情況選擇圖片存儲的方案,由於本項目實際並不會有很大的併發訪問量,因此我是選擇直接將圖片以二進制形式存儲到MySQL數據庫中。

正文

1.accountInfo.properties文件中存取數據庫的連接信息

host=139.9.149.237
user=root
passwd=123456
db=Momo
charset=utf8

2.PropertiesUtil.py文件是一個加載配置文件的工具類,用於讀取property配置文件中的數據庫信息

# encoding: utf-8
'''
@author: niko
@contact: [email protected]
@file: PropertiesUtil.py
@time: 2020/3/30 12:19
@desc:
'''

# 加載配置文件工具類
class Properties(object):
    def __init__(self, fileName):
        self.fileName = fileName
        self.properties = {}

    def __getDict(self, strName, dictName, value):

        if (strName.find('.') > 0):
            k = strName.split('.')[0]
            dictName.setdefault(k, {})
            return self.__getDict(strName[len(k) + 1:], dictName[k], value)
        else:
            dictName[strName] = value
            return

    def getProperties(self):
        try:
            pro_file = open(self.fileName, 'Ur')
            for line in pro_file.readlines():
                line = line.strip().replace('\n', '')
                if line.find("#") != -1:
                    line = line[0:line.find('#')]
                if line.find('=') > 0:
                    strs = line.split('=')
                    strs[1] = line[len(strs[0]) + 1:]
                    self.__getDict(strs[0].strip(), self.properties, strs[1].strip())
        except Exception as e:
            raise e
        else:
            pro_file.close()
        return self.properties

3.SavePicToMysql.py文件用於將圖片存儲至數據庫中

# encoding: utf-8
'''
@author: niko
@contact: [email protected]
@file: SavePicToMysql.py
@time: 2020/3/30 17:43
@desc:
'''

# 功能:將圖片轉成字節流存儲到MySQL數據庫
import pymysql

imgPath="face_picture/1.png"
# 讀取圖片文件
fp = open(imgPath, 'rb')
img = fp.read()
fp.close()

# 建立一個MySQL連接(不使用配置文件,直接填入數據庫連接信息)
conn = pymysql.connect(host='139.9.149.237', user="root", passwd="123456", db="Momo",charset='utf8')

# 創建遊標,給數據庫發送sql指令,face_table中id已經設置爲自增
cursor = conn.cursor()

try:
    # 創建數據庫表
    cursor.execute('create table if not  exists face_table(id varchar(55)primary key , imageName varchar(50),'
                   'imageData mediumblob)ENGINE=InnoDB CHARSET=utf8; ')
except Exception as e:
    print(e)
    print("table create failed")
else:
    print("table create success")

try:
    sql = "INSERT INTO face_table(id,imageName,imageData) VALUES  (%s, %s, %s);"
    imageName = imgPath.split('/')[1]
    args = ("id_"+imageName,imageName, img)
    cursor.execute(sql, args)
except Exception as e:
    print(e)
else:
    print("插入圖片成功!")

conn.commit()
# 關閉遊標
cursor.close()
# 關閉數據庫連接
conn.close()

4.ReadPicFromMysql.py文件用於從遠程數據庫中讀取圖片

# encoding: utf-8
'''
@author: niko
@contact: [email protected]
@file: ReadPicFromMysql.py
@time: 2020/3/30 19:12
@desc:
'''

import pymysql
from PropertiesUtil import Properties

#使用配置文件獲取數據庫連接信息
info = Properties("./resource/accountInfo.properties").getProperties()
host=info['host'] #主機ip地址
user=info['user']#用戶名
passwd=info['passwd']#密碼
db=info['db']#數據庫名
charset=info['charset']#字符集

conn = pymysql.connect(host=host, user=user, passwd=passwd, db=db,charset=charset)

# 創建遊標, 給數據庫發送sql指令
cur = conn.cursor()
cur.execute("select * from face_table")
rows=cur.fetchall()#二維tuple

# 讀取數據庫所有圖片
for row in rows:
    imageName=row[1]
    with open(imageName, 'wb') as fout:
        fout.write(row[2])

cur.close()
conn.close()

後記

注意如果是連接自己雲服務器的Mysql數據庫的話,一定注意在安全組中放行mysql的3306端口

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章