前言
由于项目需求,需要将识别的人脸图片存储到服务器的数据库中,经过了解得知目前业界存储图片主要有两种方式:
- 图片存储在磁盘上,即服务器文件系统中,数据库字段中保存的是图片的路径。
- 图片以二进制形式直接存储到数据库中(一般来说数据库会提供一个二进制字段来存储二进制数据。比如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: simaqingsheng@gmail.com
@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: simaqingsheng@gmail.com
@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: simaqingsheng@gmail.com
@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端口