图片标签拖拽 && url、base64、Blob、File、canvas之间相互转换

图片标签拖拽 && url、base64、Blob、File、canvas之间相互转换

背景:已有选择本地文件上传和粘贴图片上传,由于用户喜欢使用拖拽事件,提出要求会话框中的图片通过拖拽到右侧可上传区域释放后可以上传相关的图片。

问题: 拖拽聊天框中的图片和本地图片拖拽有什么不一样?传递什么数据?图片地址为什么不能就直接用当前图片地址?图片跨域(开发过程中,我的浏览器开起来允许跨域请求)

尝试: 请求允许跨域(mode: 'cros')、图片转成canvas、图片允许跨域(crossOrigin:'Anonymous'),后端服务器请求图片

  1. 先在聊天框中监听拖拽事件,携带上图片地址
ini 复制代码
    const onDrag = (e) => {
      // 携带上拖拽图片的地址
      e.dataTransfer.setData('text/plain', e.target.currentSrc);
    };
    const el = document.getElementById('im-jtalk-chat__zone');
    el?.addEventListener('dragstart', onDrag);
  1. 在拖拽目标上监听onDrop事件,获取数据传送中的图片url地址 ,通过fetch将图片转换成blob 再转换成文件。
scss 复制代码
 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'),后端服务器请求图片

  1. 先在聊天框中监听拖拽事件,携带上图片地址
ini 复制代码
    const onDrag = (e) => {
      // 携带上拖拽图片的地址
      e.dataTransfer.setData('text/plain', e.target.currentSrc);
    };
    const el = document.getElementById('im-jtalk-chat__zone');
    el?.addEventListener('dragstart', onDrag);
  1. 在拖拽目标上监听onDrop事件,获取数据传送中的图片url地址 ,通过fetch将图片转换成blob 再转换成文件。
scss 复制代码
 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
scss 复制代码
 function URLToBlob(url, callback) {
     // 图片地址需要允许跨域
    fetch(url).then(res => res.blob()).then(res => {
      callback(res)
    })
  }
URL => base64
ini 复制代码
 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
ini 复制代码
 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
javascript 复制代码
function canvasToURL(canvas) {
    return canvas.toDataURL('image/png')
  }
canvas => Blob
javascript 复制代码
function canvasToBlob(canvas, callback) {
    canvas.toBlob(blob => {
      callback(blob)
    }, "image/jpeg")
  }
base64 => Blob
ini 复制代码
// "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
ini 复制代码
 function BlobToBase64(blob, callback) {
    const a = new FileReader();
    a.readAsDataURL(blob); 
    a.onload = function (e) {
      callback(e.target?.result);
    };
  }
Blob => File
javascript 复制代码
function BlobToFile(blob) {
    return new window.File([blob], 'imageName', { type: 'text/plain' })
  }
FIle => Blob
ini 复制代码
<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
scss 复制代码
 function URLToBlob(url, callback) {
     // 图片地址需要允许跨域
    fetch(url).then(res => res.blob()).then(res => {
      callback(res)
    })
  }
URL => base64
ini 复制代码
 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
ini 复制代码
 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
javascript 复制代码
function canvasToURL(canvas) {
    return canvas.toDataURL('image/png')
  }
canvas => Blob
javascript 复制代码
function canvasToBlob(canvas, callback) {
    canvas.toBlob(blob => {
      callback(blob)
    }, "image/jpeg")
  }
base64 => Blob
ini 复制代码
// "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
ini 复制代码
 function BlobToBase64(blob, callback) {
    const a = new FileReader();
    a.readAsDataURL(blob); 
    a.onload = function (e) {
      callback(e.target?.result);
    };
  }
Blob => File
javascript 复制代码
function BlobToFile(blob) {
    return new window.File([blob], 'imageName', { type: 'text/plain' })
  }
FIle => Blob
ini 复制代码
<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)
  }
相关推荐
雪芽蓝域zzs29 分钟前
vue解构平铺VS对象包裹
前端·javascript·vue.js
风骏时光牛马1 小时前
从零到实战,完整AI学习路线
前端
三十而立洋2 小时前
深入理解 Monorepo:子包安装依赖
前端·前端工程化
IT_陈寒2 小时前
Java Stream处理大集合,我的内存怎么就炸了
前端·人工智能·后端
Captaincc2 小时前
AI 用量桌面端-桌面宠物自定义指南
前端·人工智能
OpenTiny社区3 小时前
码力全开,智启前端新生态|OpenTiny 登陆华为全联接大会2026
前端·github
妙码生花3 小时前
利用AI从零学Go并完成实战项目,完工总结:目录结构
前端·后端·go
妙码生花3 小时前
利用AI从零学Go并完成实战项目,完工总结:商业级开源产品定位和核心特性介绍
前端·后端·go
Captaincc3 小时前
掘金AI用量统计v0.1.0大更新-支持桌面宠物自定义和订阅额度卡片
前端·后端
默_笙3 小时前
🚲 从写信到打电话:WebSocket 双工通信与跨域方案的"通信进化史"
前端·javascript