使用electron属性实现保存图片并获取图片的磁盘路径

在普通的网页开发中,JavaScript由于安全性的考虑,通常是无法直接获取到客户端的磁盘路径的。浏览器出于隐私和安全原因对此类信息进行了限制。

在浏览器环境下,JavaScript主要通过Web APIs来与浏览器进行交互,而这些API通常受到浏览器的安全策略的限制。文件系统信息是被认为是敏感的信息,因此浏览器不提供直接访问客户端磁盘路径的API。所以要使用electron属性来获取。

第一步:

electron分为主进程和渲染进程,主进程就是使用electron的特性属性api,渲染进程就是我们的代码,比如vue页面代码这种。

首先我们要把项目用electron启动起来,具体怎么启动看我上一篇博客

启动完成后,找到项目文件中的backgroun.js文件,这是electron主进程的文件

把以下代码加进去

import { app, protocol, BrowserWindow ,ipcMain,ipcRenderer,dialog} from 'electron'
const fs = require('fs');
app.on('ready', async () => {// if (isDevelopment && !process.env.IS_TEST) {//   // Install Vue Devtools//   try {//     await installExtension(VUEJS_DEVTOOLS)//   } catch (e) {//     console.error('Vue Devtools failed to install:', e.toString())//   }// }createWindow()// 新增:在主进程中处理打开保存图片对话框的请求ipcMain.handle('dialog:saveImage', async (event, dataURL) => {return saveImage(dataURL);});
})// 将保存图片的逻辑封装成一个函数
async function saveImage(dataURL) {let base64 = dataURL.replace(/^data:image\/\w+;base64,/, '');let dataBuffer = Buffer.from(base64, 'base64');const options = {title: 'Save Image',buttonLabel: '保存', // 自定义保存按钮的文字defaultPath: 'image.jpg', // 默认文件名filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]};const { canceled, filePath } = await dialog.showSaveDialog(options);if (canceled) {return null; // 用户取消保存文件时返回 null} else {// 将 dataURL 保存到 filePath 的逻辑代码fs.writeFile(filePath, dataBuffer, function (err) {if (err) {console.error(err, '保存失败');} else {console.log(filePath, '保存成功');}});return filePath; // 返回用户选择的文件路径}
}
  1. 在 Electron 应用程序启动后,创建了窗口(createWindow函数应该是在代码中其他位置定义的)。
  2. 通过 ipcMain.handle 方法,为名为 'dialog:saveImage' 的事件注册了一个处理函数,用于处理保存图片对话框的请求。当渲染进程发送 'dialog:saveImage' 事件时,主进程将会执行 saveImage 函数。
  3. saveImage 函数封装了保存图片的逻辑。首先将 Data URL 转换为 Buffer 格式,然后通过 dialog.showSaveDialog 方法展示保存对话框,用户选择保存路径后,将图片文件保存到指定路径。
  4. saveImage 函数中:

  5. 首先通过 dataURL.replace 和 Buffer.from 将 Data URL 转换成了 Buffer 格式。
  6. 然后使用 dialog.showSaveDialog 方法展示保存对话框,用户选择保存路径后,通过 fs.writeFile 方法将 Buffer 写入文件。
  7. 最后根据保存成功或失败,返回相应的结果给渲染进程。

fs 是 Node.js 核心模块中的一个模块,全称为 File System(文件系统)。这个模块提供了一系列用于处理文件和文件系统的方法,可以用于读取文件、写入文件、创建目录、删除文件等操作。通过 fs 模块,你可以在 Node.js 程序中对文件和文件系统进行各种操作,包括读写文件、文件夹的操作等。

在 Electron 应用程序中,由于可以利用 Node.js 的能力,因此可以在主进程中使用 fs 模块来处理文件和文件系统相关的操作,比如在上面的代码中就使用了 fs.writeFile 方法来将图片保存到指定路径。

这是最终background.js文件的代码:

'use strict'import { app, protocol, BrowserWindow ,ipcMain,ipcRenderer,dialog} from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
// import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
const fs = require('fs');// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }
])async function createWindow() {// Create the browser window.const win = new BrowserWindow({width: 800,height: 600,webPreferences: {// Use pluginOptions.nodeIntegration, leave this alone// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more infonodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION}})win.maximize()if (process.env.WEBPACK_DEV_SERVER_URL) {// Load the url of the dev server if in development modeawait win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)if (!process.env.IS_TEST) win.webContents.openDevTools()} else {createProtocol('app')// Load the index.html when not in developmentwin.loadURL('app://./index.html')}
}// Quit when all windows are closed.
app.on('window-all-closed', () => {// On macOS it is common for applications and their menu bar// to stay active until the user quits explicitly with Cmd + Qif (process.platform !== 'darwin') {app.quit()}
})app.on('activate', () => {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) createWindow()
})// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {// if (isDevelopment && !process.env.IS_TEST) {//   // Install Vue Devtools//   try {//     await installExtension(VUEJS_DEVTOOLS)//   } catch (e) {//     console.error('Vue Devtools failed to install:', e.toString())//   }// }createWindow()// 新增:在主进程中处理打开保存图片对话框的请求ipcMain.handle('dialog:saveImage', async (event, dataURL) => {return saveImage(dataURL);});
})// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {if (process.platform === 'win32') {process.on('message', (data) => {if (data === 'graceful-exit') {app.quit()}})} else {process.on('SIGTERM', () => {app.quit()})}
}// 将保存图片的逻辑封装成一个函数
async function saveImage(dataURL) {let base64 = dataURL.replace(/^data:image\/\w+;base64,/, '');let dataBuffer = Buffer.from(base64, 'base64');const options = {title: 'Save Image',buttonLabel: '保存', // 自定义保存按钮的文字defaultPath: 'image.jpg', // 默认文件名filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]};const { canceled, filePath } = await dialog.showSaveDialog(options);if (canceled) {return null; // 用户取消保存文件时返回 null} else {// 将 dataURL 保存到 filePath 的逻辑代码fs.writeFile(filePath, dataBuffer, function (err) {if (err) {console.error(err, '保存失败');} else {console.log(filePath, '保存成功');}});return filePath; // 返回用户选择的文件路径}
}

第二步:

去渲染进程里写相关代码,也就是你的.vue文件

   //保存画布图片saveCanvasBackground() {if (this.image.url == '') return// 获取 canvas 元素和 Fabric 对象const canvas = document.getElementById("label-canvas");const fabricObj = this.fabricObj;// 将 canvas 内容保存为图片数据 URLconst dataURL = canvas.toDataURL({format: "png", // 保存的图片格式quality: 0.8, // 图片质量});//想主进程发送打开保存图片选项框请求ipcRenderer.invoke('dialog:saveImage', dataURL).then(response => {console.log(response, 'sssss');if (response) {// 接口// setsaveImage({//   img:response// }).then(res=>{//   console.log(res,'保存成功接口');// }).catch(err=>{//   console.log(err,'保存失败接口');// })} else {//用户取消}}).catch(err => {console.error(err);});// 创建一个 Blob 对象// const byteCharacters = atob(dataURL.split(",")[1]);// const byteNumbers = new Array(byteCharacters.length);// for (let i = 0; i < byteCharacters.length; i++) {//   byteNumbers[i] = byteCharacters.charCodeAt(i);// }// const byteArray = new Uint8Array(byteNumbers);// const blob = new Blob([byteArray], { type: "image/png" });// // 创建一个下载链接// const url = URL.createObjectURL(blob);// // 创建一个下载按钮并触发点击// const a = document.createElement("a");// a.style.display = "none";// a.href = url;// a.download = "saved_image.png"; // 设置下载的文件名// document.body.appendChild(a);// a.click();// // 释放对象 URL,避免内存泄漏// window.URL.revokeObjectURL(url);},

这段代码是在渲染进程中使用 ipcRenderer.invoke 方法向主进程发送了一个名为 'dialog:saveImage' 的请求,同时传递了一个名为 dataURL 的参数。当主进程处理完这个请求后,渲染进程会接收到相应的结果。

在这段代码中,使用了 ipcRenderer.invoke 方法来发送请求,并通过 Promise 对象处理响应。如果主进程成功处理了请求并返回了结果,会执行 then 中的代码,如果出现错误,会执行 catch 中的代码。

then 中的代码中,首先会打印出返回的 response,然后根据返回的结果进行相应的处理。如果 response 存在,表示图片保存成功,可以处理接口请求或其他逻辑;如果 response 不存在,表示用户取消了保存操作,可以做出相应的反应。

整体来说,这段代码的作用是在渲染进程中向主进程发送保存图片选项框的请求,并根据主进程返回的结果进行相应的处理。

以上红色框内就是运行过后获取出来当前保存图片的磁盘路径!

双击点赞!!!! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/227805.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言实现将不同数字组成无重复的三位数【一题一策】第一期

问题&#xff1a;有1、2、3、4共4个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;都是多少&#xff1f; 一、题目分析 1123124132134142143221321423124123424333123143213413243424412413421423431432 我们经过排列组合&#xff0c;判断共能组成2…

cargo(rust包管理) 常见命令、包检索 (windows+linux)

rust环境和开发环境配置&#xff1a;rust开发环境配置 winlinux Cargo是Rust的构建系统和包管理器。 如果你的能力足够强也愿意&#xff0c;可以不用cargo进行rust开发&#xff0c;即从头开始敲代码 一、cargo包相关查询 1.查找包 查找cargo包链接&#xff1a;crates.io …

RAID的介绍和选择

RAID 类型&#xff1a;什么是 RAID 以及哪种 RAID 级别适合您&#xff1f; 一、RAID 简介 在2021年6月11日&#xff0c;亚瑟迪特纳进行了一场关于RAID技术的技术讲座。RAID&#xff0c;即独立磁盘冗余阵列&#xff0c;是将多个硬盘驱动器协同工作的技术。不同的RAID类型各有优…

STM32——通用计时器

通用计时器框图 1.时钟源 1&#xff09;内部时钟(CK_INT) 2&#xff09;外部时钟模式 1&#xff1a;外部输入引脚(TIx)&#xff0c;x1&#xff0c;2&#xff08;即只能来自于通道 1 或者通道 2&#xff09; 3&#xff09;外部时钟模式 2&#xff1a;外部触发输入(ETR) 4&#…

STM32实战之IAP代码升级

目录 1 IAP介绍 2 内存分区 3 整体设计流程图 4 Boot Loader的代码编写 5 APP1代码编写 6 APP2代码编写 stm32内部flash操作相关函数 1 IAP介绍 IAP&#xff08;In Application Programming&#xff09;即在应用编程&#xff0c; IAP 是用户自己的程序在运行过程中…

解决IDEA 不能正确识别系统环境变量的问题

问题描述 本人laptop 上的是设置了GOOGLE_APPLICATION_CREDENTIALS 这个环境变量的&#xff0c; 正常java or python 的程序能基于这个环境变量使用 某个gcp service account 去访问GCP的资源 [gatemanmanjaro-x13 ~]$ env | grep -i google GOOGLE_APPLICATION_CREDENTIALS/…

vue实现H5拖拽可视化编辑器

一款专注可视化平台工具&#xff0c;功能强大&#xff0c;高可扩展的HTML5可视化编辑器&#xff0c;致力于提供一套简单易用、高效创新、无限可能的解决方案。技术栈采用vue和typescript开发, 专注研发创新工具。 <template><div:style"style":class"…

云原生机器学习平台cube-studio开源项目及代码简要介绍

1. cube-studio介绍 云原生机器学习平台cube-studio介绍&#xff1a;https://juejin.cn/column/7084516480871563272 cube-studio是开源的云原生机器学习平台&#xff0c;目前包含特征平台&#xff0c;支持在/离线特征&#xff1b;数据源管理&#xff0c;支持结构数据和媒体标…

我在 VSCode 插件里接入了 ChatGPT,解决了Bug无法定位的难题

作为一名软件开发者&#xff0c;我时常面临着代码中Bug的定位和解决问题。这个过程往往既费时又充满挑战。然而&#xff0c;最近我在我的VSCode插件中接入了ChatGPT&#xff0c;这个决定彻底改变了我处理Bug的方式。 Bug&#xff1a;开发者的噩梦 在开发过程中&#xff0c;遇…

抖音详情API:从零开始构建抖音应用

随着短视频的兴起&#xff0c;抖音已经成为了一个全球范围内的热门平台。对于开发人员而言&#xff0c;利用抖音详情API从零开始构建抖音应用具有巨大的潜力和机会。本文将为你提供从零开始构建抖音应用的指南&#xff0c;包括开发环境搭建、API请求格式、用户认证等关键环节&a…

Stable Diffusion WebUI制作光影文字效果

在huggingface上下载control_v1p_sd15_brightness模型。 将模型放在stable-diffusion-webui\extensions\sd-webui-controlnet\models目录下。 SD参数配置 正向提示词&#xff1a; city,Building,tall building,Neon Light, gentle light shines through, anime style, paint…

图像处理-周期噪声

周期噪声 对于具有周期性的噪声被称为周期噪声&#xff0c;其中周期噪声在频率域会出现关于中心对称的性质&#xff0c;如下图所示 带阻滤波器 为了消除周期性噪声&#xff0c;由此设计了几种常见的滤波器&#xff0c;其中 W W W表示带阻滤波器的带宽 理想带阻滤波器 H ( u …

Linux中安装了openjdk后jps command not found

一、问题场景 在Linux中用yum安装了openjdk-17&#xff0c;也在.bashrc中配置了环境变量JAVA_HOME以及bin目录的PATH。 但是在运行jps命令时依然报错找不到命令 二、原因分析 进入到$JAVA_HOME/bin目录查看&#xff0c;发现只有寥寥几个命令&#xff0c;压根没有jps命令&…

深入解析 Flink CDC 增量快照读取机制

一、Flink-CDC 1.x 痛点 Flink CDC 1.x 使用 Debezium 引擎集成来实现数据采集&#xff0c;支持全量加增量模式&#xff0c;确保数据的一致性。然而&#xff0c;这种集成存在一些痛点需要注意&#xff1a; 一致性通过加锁保证&#xff1a;在保证数据一致性时&#xff0c;Debez…

【日志系列】什么是分布式日志系统?

✔️什么是分布式日志系统&#xff1f; 现在&#xff0c;很多应用都是集群部署的&#xff0c;一次请求会因为负载均衡而被路由到不同的服务器上面&#xff0c;这就导致一个应用的日志会分散在不同的服务器上面。 当我们要向通过日志做数据分析&#xff0c;问题排查的时候&#…

再见2023,你好2024

再见2023&#xff0c;你好2024 生活1月 悲伤与治愈2~4月 运动与偏爱5月 体验与美食6月 婚礼与热爱7~8月 就医与别离9~11月 陪伴与暖房12月 体验&新生 运动追剧读书总结 生活 生活是一个修罗场&#xff0c;来世间一场&#xff0c;要经历丰腴有趣的人生。去体验各种滋味&…

【c++】

1.定义自己的命名空间myspace&#xff0c;并在myspace中定义一个字符 #include <iostream> #include <cstring> //<><string.h> #include <cstdio> using namespace std; //3.定义自己的命名空间myspace&#xff0c;并在myspace中定义一个字符…

【LeetCode每日一题】1154. 一年中的第几天(直接计算+调用库函数)

2023-12-31 文章目录 [1154. 一年中的第几天](https://leetcode.cn/problems/day-of-the-year/)方法一&#xff1a;直接计算思路&#xff1a; 方法二&#xff1a;调用库函数思路 1154. 一年中的第几天 方法一&#xff1a;直接计算 思路&#xff1a; 1.根据所给的字符串&#…

HTML的学习记录

<br /> 标签在 HTML 页面中创换行符。 <hr /> 标签在 HTML 页面中创建水平线。 段落是通过 <p> 标签定义的。 浏览器会自动地在段落的前后添加空行。&#xff08;<p> 是块级元素&#xff09; 文本格式 <b>This text is bold</b>字体加粗 …

win11出现安全中心空白和IT管理员已限制对某些区域的访问(不一样的解决方式),真实的个人经历,并且解决经过

1、个人的产生问题的经历 2023年12月22日&#xff0c;由于我买了一块电脑的固态硬盘1T&#xff0c;想要扩容&#xff0c;原来电脑自带512G(由于个人是一个程序员&#xff0c;导致512G实在太古鸡肋)装好以后&#xff0c;想要重装一下系统&#xff0c;来个大清理。结果不出意料&…