图片标签拖拽 && 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)
  }
相关推荐
Highcharts.js2 分钟前
步骤总结|使用 React + Highcharts 实现动态更新图表
前端·javascript·react.js·前端框架·highcharts·图表渲染
~ rainbow~2 分钟前
前端转型全栈(五)——NestJS 文件上传功能开发复盘
前端·全栈
木斯佳2 分钟前
前端八股文面经大全:来未来前端实习一面(2026-04-17)·面经深度解析
前端·校招·实习
刘佬GEO21 分钟前
GEO 效果看什么指标:从提及、引用到推荐的判断框架
前端·网络·人工智能·搜索引擎·ai
Liu.77423 分钟前
Vue 3开发中遇到的报错(1)
前端·javascript·vue.js
还有你Y6 小时前
Shell 脚本语法
前端·语法·sh
踩着两条虫8 小时前
如何评价VTJ.PRO?
前端·架构·ai编程
Mh9 小时前
鼠标跟随倾斜动效
前端·css·vue.js
小码哥_常10 小时前
Kotlin类型魔法:Any、Unit、Nothing 深度探秘
前端
Web极客码11 小时前
深入了解WordPress网站访客意图
服务器·前端·wordpress