Django 实现将图片转为Base64,然后使用json传输
最近使用Django来进行图像的传输,由于要求需要使用Json格式进行请求,所以我们尝试了二进制编码放在json里,发现bytes格式不能打入json,于是转为了base64
将图片转为json
图片转为json有2中方法,一个是二进制后再转,一个是转为矩阵以后再转。
importbase64
importcv2
#通过opencv转base64
img_im=cv2.imread("D://32.png")
aa=base64.b64encode(cv2.imencode('.jpg',img_im)[1]).decode()
print(len(aa))#17292
#通过bytes再转base64
bb=base64.b64encode(open("D://32.png",'rb').read())
print(len(bb))#43848
最后采用了Opencv的方式,主要发现opencv的base64编码比第二种短一半,所以用了第一种。
客户端请求发送数据格式
客户端请求服务器的base64,目前我这里发现2中,通过Postman测试。
第一种‘form/data':
#客户端:
image1=cv2.imread("D://32.png")
aa=base64.b64encode(cv2.imencode('.jpg',image1)[1]).decode()
r=requests.post(url,data={"image":image1})
print(r.content.decode("utf-8"))
#服务端:
defimage_base64(request):
result=request.POST.get("image")
img_byte=base64.b64decode(result)
img_np_arr=np.fromstring(img_byte,np.uint8)
image=cv2.imdecode(img_np_arr,cv2.IMREAD_COLOR)
#image已经转为矩阵了
第二种‘application/json':
#客户端:
image1=cv2.imread("D://32.png")
aa=base64.b64encode(cv2.imencode('.jpg',image1)[1]).decode()
r=requests.post(url,json={"image":image1})
print(r.content.decode("utf-8"))
#服务端:
deflocal_ocr_base64(request):
#result=request.POST.get("image")
data=request.body
data_json=simplejson.loads(data)#data是str格式的,需要转为json
result=data_json["image"]
img_byte=base64.b64decode(result)
img_np_arr=np.fromstring(img_byte,np.uint8)
image=cv2.imdecode(img_np_arr,cv2.IMREAD_COLOR)
补充知识:Django将多个图片保存成一个URL串返回给前端
说明
Django有ImageField字段,是封装好的,使用很方便,但是一个ImageField字段只能保存一张图片的URL,我现在是想将多张图片保存在一个字段里,然后URL和URL之间用一个自定义的分隔符连接起来,这样不用为了图片再设计一个字表。
自定义上传图片
设置settings.py文件,添加如下语句
MEDIA_URL='/media/'
MEDIA_ROOT=os.path.join(BASE_DIR,'media/')
IMAGE_ROOT=os.path.join(MEDIA_ROOT,'images/')
WEB_HOST_MEDIA_URL=os.path.join('http://127.0.0.1:8000',MEDIA_URL[1:],'images/')
MEDIA_ROOT代表的是用户上传后的文件一般保存的地方,一般在放在项目目录下,例如BASE_DIR就是取得项目绝对地址。而MEDIA_URL是指URL访问时的URL。例如,
BASE_DIR:/Users/incisor/VSCodeProjects/python/Notes
那么
MEDIA_ROOT:/Users/incisor/VSCodeProjects/python/Notes/media
假设media目录下有一张图片2019.jpg,那么
MEDIA_URL:http://127.0.0.1:8000/media/
然后再通过http://127.0.0.1:8000/media/2019.jpg这个URL是可以直接访问这个图片的。
IMAGE_ROOT是我自定义的一个字段,因为我想以后可能会上传视频,或者其他一些文件,想区分开,所以我在media目录下再建了一个目录images,那么
IMAGE_ROOT:/Users/incisor/VSCodeProjects/python/Notes/media/images
WEB_HOST_MEDIA_URL是拼接URL时使用,因为我接下来要自己拼接多个图的URL,MEDIA_URL[1:]的原因时如果不去掉第一个/,那WEB_HOST_MEDIA_URL会是/media/images/,这显然不是我们想要的,所以需要把第一个/去掉。
views.py文件
前端传过来不定数量的图片,可能0张,最多9张,每个图片都做base64编码再传过来,POST请求里有个参数imgs,是一个数组,保存base64编码。
base64编码如下图所示,这只是一部分:
前面的data:image/png;base64,除了后缀会不同,其他的是固定的,所以我会先从这里取得后缀png,再做编码转换。
importbase64
importos
importre
fromdatetimeimportdate,datetime
fromrest_frameworkimportstatus
fromrest_framework.decoratorsimportapi_view
fromrest_framework.responseimportResponse
fromNotes.settingsimportIMAGE_ROOT,WEB_HOST_MEDIA_URL
@api_view(['POST',])
defimages(request):
urls=''
dir_name=date.today().__str__().replace('-','_',2)#2019_06_21
dirs=os.path.join(IMAGE_ROOT,dir_name)#将日期作为目录名
ifnotos.path.isdir(dirs):
os.makedirs(dirs)#判断目录是否存在,不存在则创建
forimginrequest.data['imgs']:
strs=img.split(',')
suffix=re.findall(r'/(\w+?);',strs[0])[0]#取得文件后缀
#拼接服务器上的文件名
#datetime.now()取得当前时间,精确到了微秒,一般来说是唯一的了,因为目录是日期,所以文件名就去掉日期,最后会是一串数字
img_name=re.sub(r':|\.','',datetime.now().__str__().split('')[1])+'.'+suffix
img_path=os.path.join(dirs,img_name)
withopen(img_path,'wb')asout:
out.write(base64.b64decode(strs[1]))#base64解码,再写入文件
out.flush()
urls+=os.path.join(WEB_HOST_MEDIA_URL,dir_name,img_name)+'[/--sp--/]'#拼接URL,URL与URL之间用[/--sp--/]隔开
result={}
result['status']=status.HTTP_200_OK
result['message']='图片上传成功'
result['urls']=urls[:len(urls)-len('[/--sp--/]')]#去掉末尾的[/--sp--/]
returnResponse(data=result)
3、urls.py文件
fromdjango.contribimportadmin
fromdjango.urlsimportpath
fromdjango.conf.urls.staticimportstatic#需要添加这句,包含静态资源之类的
fromnoteimportviews
from.importsettings
urlpatterns=[
path('notes/images/',views.images),
path('admin/',admin.site.urls),
]
urlpatterns+=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)#这句不设置的话,不能通过URL直接访问到图片
4、启动服务,python3manage.pyrunserver
5、POST请求,然后返回对应的JSON数据
{
"status":200,
"message":"图片上传成功",
"urls":"http://127.0.0.1:8000/media/images/2019_06_21/073249204253.png[/--sp--/]http://127.0.0.1:8000/media/images/2019_06_21/073249854323.png"
}
这样在数据库方面,就可以直接用一个varchar类型来存储多张图了,前端收到URL串,再按照定好的分隔符[/–sp–/]切开后,就可以显示了。
以上这篇Django实现将图片转为Base64,然后使用json传输就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。