【CEP教程-13】nodejs在插件开发中的应用

【CEP教程-13】nodejs在插件开发中的应用

前面的文章我们学习到,CEP的插件面板,是基于浏览器的web开发生态,我们通过Html/css/js来编写面板的结构、样式和交互,通过调用ExtendScript来操控宿主Ps。

除此之外,Adobe还在这个浏览器里头嵌入了nodejs的运行时,可以让我们在面板开发的时候使用nodejs的各种特性,这无疑大大的扩展了插件面板的能力,这篇文章我们就来介绍一下如何在CEP插件面板中使用nodejs,以及一些特性的应用吧

nodejs embed

本篇文章不讲nodejs本身的知识,如果从来没有用过nodejs,请出门左转百度一下学习相关的基础知识再来。

配置

由于安全考虑,CEP在默认情况下是关闭了nodejs的支持的,要打开node环境,我们需要在manifest.xml文件中进行打开开关,如下

1
2
3
4
5
6
7
<Resources>
<MainPath>./index.html</MainPath>
<CEFCommandLine>
<Parameter>--enable-nodejs</Parameter>
</CEFCommandLine>
<ScriptPath>./jsx/main.jsx</ScriptPath>
</Resources>

通过在CEF的启动命令添加参数 –enable-nodejs,就可以开启node环境了。打开node环境之后,浏览器中会注入如下几个node全局对象

  • global, GLOBAL, root
  • Buffer nodejs的Buffer类,一般用来存储二进制数据之用
  • process nodejs处理线程相关的类
  • require 这个就是node开发最开始的函数了,你可以通过它来引入其它各种库
  • module nodejs的内置模块类

如果熟悉node开发的小伙伴,其实就心理有底了,我们可以通过require引入nodejs内置的各个模块,或者通过npm install安装第三方的功能模块,下面的文章中我们会通过一些例子来介绍。

注意: 这里有一个很需要关注的地方,由于node注入了全局require函数,所以你就不能自己在用require函数了,这个在你用一些第三方库如requireJS这样的情况下会有问题。

存取本地文件

在插件开发过程中,我们经常会遇到一种场景:需要保存用户的一些信息,比如登录的账号,面板的一些配置等等,这些信息需要存储到本地文件当中,下次进来的时候,读取出来。虽然cep本身也提供了一些文件读取的api,但是易用性并不太好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 通过cep的api创建一个文件
var path = "/tmp/test";
var result = window.cep.fs.makedir(path);
if (0 == result.err) {
// success
} else {
// fail
}

// 通过cep的api写入文件
var data = "This is a test.";
var path = "/tmp/test";
var result = window.cep.fs.writeFile(path, data);
if (0 == result.err){
// success
} else {
//
}

有了nodejs提供的特性,我们可以通过它来做文件的读取, 在我们的插件面板项目中,执行

1
npm init

将生成一个package.json文件,后续我们安装的第三方库都会在这里显示。然后我们可以通过nodejs内置的fs, path模块来操作文件。由于本地存储会涉及到操作系统相关的内容,我们可以通过process来判断当前是windows还是mac

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
const fs = require("fs");
const path = require("path");

// 判断当前系统是win还是mac
function os() {
return process.platform === 'win32'? 'win' : 'mac';
}

// 获取当前的用户目录
function getUserDirectory() {
if (os() === 'win') {
return path.join(process.env["USERPROFILE"], 'AppData', 'Roaming');
} else {
return path.join(process.env["HOME"], 'Library', 'Application Support');
}
}

// 在用户目录下创建一个文件夹
// 返回该文件夹的路径
function createPluginDir(name) {
const home = getUserDirectory();
const dir = path.join(home, name);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
return dir;
}

// 将用户的信息写入到文件中
function writeUserInfo(data, filename) {
const dir = createPluginDir("my_plugin");
const file = path.join(dir, filename);
fs.writeFileSync(file, data);
}

// 从本地文件夹中读取文件内容
function readUserInfo(filename) {
const dir = createPluginDir("my_plugin");
const file = path.join(dir, filename);
if (fs.existsSync(file)) {
return fs.readFileSync(file, "utf8");
}
return null;
}

上面代码中的函数片段,就是基本的本地存储过程了,我可以通过writeUserInfo来写一些本地文件,通过readUserInfo来读取文件内容,由于文件读取属于io操作,一般是通过异步手段来处理的,这里我为了简便和容易理解,全部采用的同步函数。

1
2
3
4
5
6
7
8
9
const userData = JSON.stringify({
email: "zhansan@126.com",
age: 18,
role: 'guest'
});
writeUserInfo(userData, "userinfo.json");

const user = JSON.parse(readUserInfo("userinfo.json"));
console.log(user.email); // zhansan@126.com

文件的存取是一个非常简单的操作,但也是非常基础和常用,建议大家自己动手写一写,非常容易。在文件操作的过程中,有一些地方需要比较注意的就是中文路径和windows的反斜杠问题,路径的拼接,尽量不要自己用字符串去拼,尽量用path提供的函数

1
2
path.join()
path.resolve()

针对中文字符可能需要encode,windows的路径传递要对 \ 进行转义 \\

上传/下载文件

有时候我们的插件需要支持上传/下载文件,比如一个你要做一个相册的插件,点击面板上的图片缩略图,从服务器上下载原图,并用Ps打开这张原图。这个场景就需要通过CEP面板来下载远程图片资源,虽然使用AJAX也能实现,但是代码写起来要很繁琐。但是既然有了nodejs,我们就可以用第三方库来实现这个功能了。

首先安装第三方库axios,执行完成之后,在你的插件目录下就会出现一个node_modules文件夹,该文件夹下存放第三方库和它的依赖,这个文件夹最后要和你的插件一起发布。

1
npm install --save axios

安装完成之后,我们就可以通过它来下载文件了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const axios = require("axios");
const fs = require("fs");

// 从给的url下载图片资源到本地插件文件夹
function downloadImage(url, name) {
return new Promise((resolve, reject) => {
const dir = createPluginDir("my_plugin");
axios({
method: "get",
url,
responseType: 'arraybuffer'
}).then((res) => {
const buffer = res.data;
const file = path.join(dir, name + '.png');
fs.writeFileSync(file, buffer, 'binary');
resolve(file);
});
})
}

上面的downloadImage可以将我们传进去的url图片下载到本地插件文件夹中,并返回该图片的路径,我们拿到路径之后,可以调用ExtendScript来让Ps打开该图片,由于网络下载是异步的,所以上面的代码用到了Promise,基本上高版本的Ps带的CEF都是支持的,可以放心使用。

其它用途

除了上面介绍的很常见的功能之外,nodejs由于提供了非常丰富的第三方库,和能够和本地系统对接的能力,经常会被用在这些地方

1. 获取电脑的系统和硬件信息

你可以通过os模块来获取到当前电脑的系统各项属性,还可以拿到本地的ip,mac地址或者硬盘,网卡的一些参数,这些信息经常被用来做插件的单机电脑授权来使用。

2. 加密数据

你可以用cryptojs库来做一些数据的加密处理,以实现一些安全策略,避免插件被用户破解之类的

3. 网络传输

除了上面介绍的图片下载之外,你还可以通过很多第三方好用库来实现httpsocket,websocket等客户端,甚至是服务器端,你可以在插件上起一个WebSocket服务器来监听链接,然后用其它设备去链接它,这样你就可以远程控制这个Ps了。

4. 生成器

除了插件面板之外,Ps提供的生成器就是一个完整的node服务,这个在前面的文章已经详细介绍了

总结

nodejs以其丰富务必的生态和能力,给CEP的插件开发提供了非常多的可能,这也是我非常喜欢CEP这套架构的原因。如果还没有用过nodejs的小伙伴,强烈推荐去学习,并且将其应用到CEP插件开发中来,这能够大大的提升的开发效率和产品特性。

由于插件集成nodejs非常容易,所以本篇文章内容不多,以介绍入门为主,能够用nodejs做出什么名堂来,还是得靠各位自己的idea不断去探索。下一篇文章我们介绍插件的存储相关内容,敬请期待~~

【CEP教程-13】nodejs在插件开发中的应用

https://uiscripting.com/2022/03/17/cep-with-nodejs/

作者

小强

发布于

2022-03-17

更新于

2023-03-07

许可协议

评论