背景
在做前端开发的过程中,做过很多的项目,都会遇到图片预览和展示。一般的图片都是用于页面美化,信息解释说明的作用。但是在接触某些业务场景时,例如用户注册需要上传用户个人身份证照片,办理业务需要上传证明材料图片,这类图片信息属于个人隐私,在网络传输过程中,可能会出现泄露,极大的安全风险。所以对于涉及个人隐私的图片在网络传输过程中有极大的安全要求。
解决方案
图片上传
上传图片过程中,传输数据指定为二进制类型,在request请求体,Header上加入token校验。后台可通过token校验,验证上传用户的合法性,同时该token具备时效性,过段时间token会失效,时间间隔可自定义完成。
图片下载
图片下载过程中,同样在request请求体,Header上加入token校验。token的校验机制与图片上传相同,前端通过接二进制流后,转化为base64图片格式进行展示。
代码实现
前端图片上传处理逻辑
此处我的实例是图片上传,实际情况上传的文件加判断逻辑。
getFileName(event){
var file = event.target.files;
var fileName = file[0].name;
var arr_index = fileName.lastIndexOf(".");
var ext = fileName.substr(arr_index+1).toUpperCase(); //图片上传文件格式校验逻辑
ext = ext.toLowerCase();
if (ext!='jpg' && ext!='png'){
this.$Modal.error({
title: '温馨提示',
content: '文件只能上传jpg或者png格式文件。'
})
}else{
var formData = new FormData();
formData.append('file',file[0]);
this.uploadFileMethod(formData);
}
},
uploadFileMethod(formData){
let self = this;
let params={
fileData:formData
}
uploadFileForImage(params).then(res=>{
if (res.data&&res.data.success) {
// 上传完成时逻辑
}
self.$store.commit('showLoadingFlag', false)
})
}
前端图片查看及下载处理逻辑:
// 图片展示逻辑
loadImageMethod (imageid) {
let self = this
getImagesDetail(imageid).then(res => {
if (res) {
var blob = res
if (blob.size > 0) {
// 转换为base64,可以直接放入img标签src中
var reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = function (e) {
self.imageSrc = e.target.result
}
} else {
self.$Message.error('未找到图片资源')
}
}
}, function (err) {
self.$Message.error('服务器异常')
})
}
//图片下载
downloadImage(index){
let aLink = document.createElement('a');
aLink.download = this.imageList[index].catelogname+'.jpg';
aLink.href = this.imageSrc;
aLink.click();
}
后端请求api调用实例如下:
import filerequest from '@/libs/api.file.request'
export const getImagesDetail = (imageid) => {
return filerequest.request({
url: '/activity/images/' + imageid ,
method: 'GET'
})
}
图片上传和下载核心逻辑:
在前端通用公共逻辑的文件夹下,创建文件fileRquest的文件:
import FileRequest from '@/libs/FileRequest'
const filerequest = new FileRequest()
export default filerequest
此处是自己通过promise封装的上传和下载调用的方法:
注:在获取接受文件流的,需要指定返回的类型,即responseType 为 "blob";
import config from '@/config'
const baseUrl = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.pro
class FileRequest {
request (options) {
if(options.data&&options.method.toLocaleLowerCase() === "post"){
return new Promise(function(resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(options.method,baseUrl+options.url)
//以下为传入token值
xhr.setRequestHeader("usertoken",'xxxxxx');
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.onload = function (res) {
if (this.status === 200) {
resolve(this.response);
}else{
reject(this.response);
}
}
xhr.send(options.data);
})
}else{
return new Promise(function(resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(options.method,baseUrl+options.url)
xhr.setRequestHeader("usertoken",store.getters.token);
//注意获取接文件流需要指定,返回类型为blob
xhr.responseType = "blob";
xhr.onload = function (res) {
if (this.status === 200) {
resolve(this.response);
}else{
reject(this.response);
}
}
xhr.send();
})
}
}
}
export default FileRequest