图片标签拖拽 && url、base64、Blob、File、canvas之间相互转换
背景:已有选择本地文件上传和粘贴图片上传,由于用户喜欢使用拖拽事件,提出要求会话框中的图片通过拖拽到右侧可上传区域释放后可以上传相关的图片。
问题: 拖拽聊天框中的图片和本地图片拖拽有什么不一样?传递什么数据?图片地址为什么不能就直接用当前图片地址?图片跨域(开发过程中,我的浏览器开起来允许跨域请求)
尝试: 请求允许跨域(mode: 'cros')、图片转成canvas、图片允许跨域(crossOrigin:'Anonymous'),后端服务器请求图片
- 先在聊天框中监听拖拽事件,携带上图片地址
const onDrag = (e) => {
// 携带上拖拽图片的地址
e.dataTransfer.setData('text/plain', e.target.currentSrc);
};
const el = document.getElementById('im-jtalk-chat__zone');
el?.addEventListener('dragstart', onDrag);
- 在拖拽目标上监听onDrop事件,获取数据传送中的图片url地址 ,通过fetch将图片转换成blob 再转换成文件。
const getImageFileFromUrl = (url, imageName, callback) => {
fetch(url)
.then((res) => {
return res.blob();
})
.then((blob) => {
const imgFile = new File([blob], imageName, { type: "image/jpeg" });
callback(imgFile);
});
}
// 选择默认图片
const chooseStaticImg = (imageUrl) => {
getImageFileFromUrl(imageUrl, "image.png", (file) => {
//获取file对象 图片处理方法
changeFileList(file)
});
}
const imgUrl = e.dataTransfer.getData("text");
// 拖拽的不是文件 && 拖拽图片被赋值了图片链接
if(!e.dataTransfer.files?.length && imgUrl) {
chooseStaticImg(imgUrl);
}
其中有坑,图片fetch是走了接口请求,这里就会有跨域问题,需要后端设置允许图片跨域下载
以下是几种图片格式之间的转换:
图片标签拖拽 && url、base64、Blob、File、canvas之间相互转换

背景:已有选择本地文件上传和粘贴图片上传,由于客服喜欢使用拖拽事件,提出要求会话框中的图片通过拖拽到右侧可上传区域释放后可以上传相关的图片。
问题: 拖拽聊天框中的图片和本地图片拖拽有什么不一样?传递什么数据?图片地址为什么不能就直接用当前图片地址?图片跨域(开发过程中,我的浏览器开起来允许跨域请求)
尝试: 请求允许跨域(mode: 'cros')、图片转成canvas、图片允许跨域(crossOrigin:'Anonymous'),后端服务器请求图片
- 先在聊天框中监听拖拽事件,携带上图片地址
const onDrag = (e) => {
// 携带上拖拽图片的地址
e.dataTransfer.setData('text/plain', e.target.currentSrc);
};
const el = document.getElementById('im-jtalk-chat__zone');
el?.addEventListener('dragstart', onDrag);
- 在拖拽目标上监听onDrop事件,获取数据传送中的图片url地址 ,通过fetch将图片转换成blob 再转换成文件。
const getImageFileFromUrl = (url, imageName, callback) => {
fetch(url)
.then((res) => {
return res.blob();
})
.then((blob) => {
const imgFile = new File([blob], imageName, { type: "image/jpeg" });
callback(imgFile);
});
}
// 选择默认图片
const chooseStaticImg = (imageUrl) => {
getImageFileFromUrl(imageUrl, "image.png", (file) => {
//获取file对象 图片处理方法
changeFileList(file)
});
}
const imgUrl = e.dataTransfer.getData("text");
// 拖拽的不是文件 && 拖拽图片被赋值了图片链接
if(!e.dataTransfer.files?.length && imgUrl) {
chooseStaticImg(imgUrl);
}
其中有坑,图片fetch是走了接口请求,这里就会有跨域问题,需要后端设置允许图片跨域下载
以下是几种图片格式之间的转换:

URL => Blob
function URLToBlob(url, callback) {
// 图片地址需要允许跨域
fetch(url).then(res => res.blob()).then(res => {
callback(res)
})
}
URL => base64
function URLToBase64(url, callback) {
let image = new Image();
// CORS 策略,会有跨域问题
image.setAttribute("crossOrigin",'Anonymous');
image.src = url;
image.onload = function() {
let canvas = document.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
// 将图片插入画布并开始绘制
canvas?.getContext('2d')?.drawImage(image, 0, 0);
// result
let result = canvas.toDataURL('image/png')
callback(result)
};
}
URL => canvas
function URLToBase64(url, callback) {
let image = new Image();
// CORS 策略,会有跨域问题
image.setAttribute("crossOrigin",'Anonymous');
image.src = url;
image.onload = function() {
let canvas = document.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
// 将图片插入画布并开始绘制
canvas?.getContext('2d')?.drawImage(image, 0, 0);
callback(canvas)
};
}
canvas => URL
function canvasToURL(canvas) {
return canvas.toDataURL('image/png')
}
canvas => Blob
function canvasToBlob(canvas, callback) {
canvas.toBlob(blob => {
callback(blob)
}, "image/jpeg")
}
base64 => Blob
// "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby
// blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
function Base64ToBlob(base64) {
const arr = base64.split(",");
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
Blob => base64
function BlobToBase64(blob, callback) {
const a = new FileReader();
a.readAsDataURL(blob);
a.onload = function (e) {
callback(e.target?.result);
};
}
Blob => File
function BlobToFile(blob) {
return new window.File([blob], 'imageName', { type: 'text/plain' })
}
FIle => Blob
<input type="file" accept="image/*" onChange={onChange} />
function FileToBlob (file) {
let url = window.URL.createObjectURL(file.item[0]);
return url;
}
const onChange = (e) => {
FileToBlob(e.nativeEvent.srcElement.files)
}
URL => Blob
function URLToBlob(url, callback) {
// 图片地址需要允许跨域
fetch(url).then(res => res.blob()).then(res => {
callback(res)
})
}
URL => base64
function URLToBase64(url, callback) {
let image = new Image();
// CORS 策略,会有跨域问题
image.setAttribute("crossOrigin",'Anonymous');
image.src = url;
image.onload = function() {
let canvas = document.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
// 将图片插入画布并开始绘制
canvas?.getContext('2d')?.drawImage(image, 0, 0);
// result
let result = canvas.toDataURL('image/png')
callback(result)
};
}
URL => canvas
function URLToBase64(url, callback) {
let image = new Image();
// CORS 策略,会有跨域问题
image.setAttribute("crossOrigin",'Anonymous');
image.src = url;
image.onload = function() {
let canvas = document.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
// 将图片插入画布并开始绘制
canvas?.getContext('2d')?.drawImage(image, 0, 0);
callback(canvas)
};
}
canvas => URL
function canvasToURL(canvas) {
return canvas.toDataURL('image/png')
}
canvas => Blob
function canvasToBlob(canvas, callback) {
canvas.toBlob(blob => {
callback(blob)
}, "image/jpeg")
}
base64 => Blob
// "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby
// blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
function Base64ToBlob(base64) {
const arr = base64.split(",");
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
Blob => base64
function BlobToBase64(blob, callback) {
const a = new FileReader();
a.readAsDataURL(blob);
a.onload = function (e) {
callback(e.target?.result);
};
}
Blob => File
function BlobToFile(blob) {
return new window.File([blob], 'imageName', { type: 'text/plain' })
}
FIle => Blob
<input type="file" accept="image/*" onChange={onChange} />
function FileToBlob (file) {
let url = window.URL.createObjectURL(file.item[0]);
return url;
}
const onChange = (e) => {
FileToBlob(e.nativeEvent.srcElement.files)
}