当前位置: 首页 > article >正文

【electron8】electron实现“图片”的另存为

注:该列出的代码,都在文章内示例出

1. 另存为按钮事件:

const saveAsHandler = async () => {
    const { path, sessionId } = recordInfo
    if(typeof message !== 'string') return;
    // 因为我的图片是加密的,所以我需要根据接口返回的路径,然后根据不同图片的密钥(sessionId)去进行解密(decodeAvatarUrl)处理,最后返回blob,所以这块儿不必纠结
    const res = await decodeAvatarUrl(path, sessionId, false)
    // blob转ArrayBuffer
    blobToArrayBuffer(res, async (buffer: ArrayBuffer) => {
      const type = await getImageType(res) // 将Blob数据传给getImageType,经处理后获取图片类型, 请看标题2的代码示例
      // saveAsPicture 这个就是渲染进程与Electron的通信 ,请看标题3的代码示例
      saveAsPicture({ buffer, name: getNowTime(), type })
        .then(() => setOpen(false))
    })
  }

2. getImageType代码:

/**
 * get image type In image buffer
 */
export function getImageType (blob: Blob) {
  return new Promise((resolve: (type: string) => void, reject) => {
    const reader = new FileReader();
    reader.onload = (event: any) => {
      // 使用Uint8Array和DataView来读取文件头部
      const arr = new Uint8Array(event.target.result);
      const view = new DataView(arr.buffer);

      // 根据文件头部的magic number判断文件类型
      switch (view.getUint16(0, false)) {
        case 0xffd8: // JPEG
          resolve('image/jpeg');
          break;
        case 0x8950: // PNG
          resolve('image/png');
          break;
        case 0x4749: // GIF
          resolve('image/gif');
          break;
        case 0x4949: // TIFF
        case 0x4d4d: // TIFF
          resolve('image/tiff');
          break;
        default:
          reject(new Error('Unsupported image type'));
      }
    };
    reader.onerror = reject;

    // 读取Blob为ArrayBuffer
    reader.readAsArrayBuffer(blob);
  })
}

3. saveAsPicture的主要代码:

/** 校验:另存为 */
type saveAsPicturePrams = {
  buffer: ArrayBuffer;
  name: string;
  type: string;
} 
/** 另存为 */
export const saveAsPicture = (params: saveAsPicturePrams) => {
  // 关于与Electron的UI.SAVEASPATH的通信,请看标题4
  return ipcRenderer.invoke(UI.SAVEASPATH, params)
}

4. Electron进程与渲染进程的交互

/**
 * 对话窗口:另存为图片时,需要获取选择要存储的路径
 * @param buffer 数据
 * @name 文件名
 * @type 文件类型
 */
ipcMain.handle(UI.SAVEASPATH, (e, arg: { buffer: ArrayBuffer, name: string, type: string; }) => {
  return new Promise(async (resolve, reject) => {
    const { buffer, name, type } = arg;
    const imageType = type?.split('/').pop() //获取图片格式
    const imageName = `xxxxxxx_${name}`
    const defaultPath = path.join(app.getPath('downloads'),`${imageName}.${imageType}`)
    
    await dialog.showSaveDialog(mainWindow, {
      title: '另存为...',
      buttonLabel: '保存',
      defaultPath,
      properties: ['createDirectory'],
      filters: [{
        name: `图片文件(*.${imageType})`,
        extensions: [imageType]
      }]

    }).then((res: any) => {
      if(res.canceled) {
        resolve(res)
        return;
      };
      fs.writeFileSync(res.filePath, new DataView(buffer))
      resolve(res)
    })
  })
  
})

效果图:

在这里插入图片描述


http://www.kler.cn/a/369746.html

相关文章:

  • STM32 TIM输入捕获 测量频率
  • C++并发编程指南02
  • Greenplum临时表未清除导致库龄过高处理
  • Java面试题2025-并发编程进阶(线程池和并发容器类)
  • 27.useFetch
  • 一组开源、免费、Metro风格的 WPF UI 控件库
  • JavaScript数组常用方法 - 2024最新版前端秋招面试短期突击面试题【100道】
  • cobalt strikemetasploit 小记
  • appium 的工作原理
  • 【教程】如何查看IEEE会员证书Membership Card
  • OpenCV中的坐标运算 [C#]
  • 记录一个容器间访问不通问题
  • 学习记录:js算法(七十八):划分字母区间
  • webpack常用插件有哪些??
  • .NET 8 中的 Mini WebApi
  • Pandas行转列与列装行
  • 本地docker部署中间件和应用
  • 使用 v-html 指令渲染的标签, 标签内绑定的 click 事件不生效
  • Linux开放端口问题(同一局域网)
  • Django入门教程——动态表格分页展示数据
  • 指令(一):Android OS实用指令
  • 【入驻电商平台指南】ISV入驻京东平台申请流程
  • Redis内部数据结构Dict结构详解
  • 关于写“查看IT设备详细信息”接口的理解
  • PostgresSql 常用运维命令
  • 【大数据学习 | Zookeeper】Zookeeper的选举机制