自动化上传图片到ftp并刷新链接发送通知
场景需求:
因为业务需要,在网站上维护首页的二维码群,群满后就需要更换新的二维码图片,
并且这个图片在网站很多地方都用到,所以基本上每周都要更换几次;
具体链接:https://www.xmf.com/
没有自动化之前的更换流程:
运营建群 --》发送给我二维码图片---》我上传到ftp的指定图片目录---》到网站首页找下图片的url地址 ---》通知另一位同事帮忙刷新下图片的链接
自动化之后的流程:
运营发送给我二维码图片---》我把图片放到一个文件夹中---》完成(程序自动执行任务更换二维码)
自动化思路:
- 把要替换的图片放到refesh_url文件夹中根目录下 手动
- 监测文件夹中图片类型文件的变化
- 运行js更改图片的名称为wxGroupErcode.png
- 上传图片到正式环境服务器中
- 调用刷新接口刷新图片链接
- 发送机器消息到群里,通知刷新成功并附带上图片的链接地址
- 删除文件夹中的图片
程序实现:
const fs = require("fs")
const request = require("request")
const FTP = require("ftp")
const ftp = new FTP()
const pro = require("child_process")
const { getData } = require("./pro")
const { url, text, base_path, password, user, host } = getData()
// 刷新url
function refesh_url() {
return new Promise((resolve, reject) => {
request.get(" 刷新链接的接口", { strictSSL: false }, (err, res, body) => {
if (res.statusCode == 200) {
resolve()
}
if (err) {
reject()
}
})
})
}
// 机器人发送消息
function robot_message() {
robot_url = "企业微信群中建立的一个机器人的链接"
headers = { "content-type": "application/json" }
var data = {
"msgtype": "text",
"text": {
"content":
text + "链接刷新成功 " + url,
}
}
return new Promise((resolve, reject) => {
request({
method: "POST",
url: robot_url, headers,
json: true,
body: data
}, (error, res, body) => {
if (error) {
console.error(error)
reject(error)
return
}
if (res.statusCode == 200) {
resolve()
}
})
})
}
// 删除图片文件
function remove_img() {
return new Promise((resolve, reject) => {
fs.unlink("./wxGroupErcode.png", (err) => {
if (err) {
reject(err)
console.log(err)
} else {
resolve()
console.log("----------------删除成功命名")
}
})
})
}
// 重命名图片
function rename_img(filename) {
return new Promise((resolve, reject) => {
fs.promises.rename(filename, "./wxGroupErcode.png").then(() => {
console.log("-------重命名成功---------")
resolve()
}).catch(err => {
reject(err)
})
})
}
async function init() {
fs.watch("./", (event, filename) => {
if (filename) {
if (filename.endsWith(".jpg") || (filename.endsWith(".png") && filename != "wxGroupErcode.png")) {
// 监测到有jpg文件 就重命名为png的文件
// 重命名文件
rename_img(filename).then(res => {
pro.exec("node ftp_img.js", (err, stdout, stderr) => {
if (err) {
// err.code 是进程退出时的 exit code,非 0 都被认为错误
// err.signal 是结束进程时发送给它的信号值
console.log('err:', err, err.code, err.signal);
}
console.log('stdout:', stdout);
console.log('stderr:', stderr);
refesh_url().then(() => {
robot_message().then(() => {
remove_img()
})
})
})
})
}
console.log('filename provided: ' + filename);
} else {
console.log('filename not provided');
}
})
}
init()
上传到ftp的js
const FTP = require("ftp")
const ftp = new FTP()
const { getData } = require("./pro")
const { url, base_path, password, user, host } = getData()
function upload_file(targetPath, name = "wxGroupErcode.png") {
ftp.put(name, targetPath + "/" + name, err => {
ftp.end()
if (err) {
console.log(err)
return
}
console.log(`upload file has completed,filePath:${targetPath}`)
console.log("-----------上传完成-----------------")
})
}
ftp.connect({
host,
user,
password,
port: 21,
"secure": true,
"secureOptions": { "rejectUnauthorized": false }
})
ftp.on("ready", () => {
upload_file(base_path)
})
还有一个重要的代码:
程序的开发肯定的先要在测试环境开发,然后在正式环境使用,要是每次都换来换去也太麻烦了,所以就引入了 区分正式环境和测试环境变量的库,然后执行命令的可以了
pro.js 文件
console.log(process.env.NODE_ENV)
function getData() {
var o = {}
if (process.env.NODE_ENV == "production") {
// 存放正式环境的一些数据
} else {
// 存放测试环境的一些关键性数据
}
return o
}
module.exports = {
getData
}
然后在package.json中配置如下
"scripts": {
"dev": "cross-env NODE_ENV=development node ./index.js",
"pro": "cross-env NODE_ENV=production node ./index.js"
},
这样npm run dev就是执行测试环境 npm run pro就是执行正式环境
注意事项:
- 配置区分正式和测试环境的变量需要下载 cross-env这个第三方库;
- ftp链接因为安全性问题不能被封装成函数在需要的时候调用,所以需要使用到node的子进程去执行ftp_img.js文件,这个文件中专门用来写ftp链接和上传相关的代码,这是子进程异步调用js文件pro.exec("node ftp_img.js",callback)
- ftp在连接的时候一定要加上最后两个参数,不然因为安全性问题,ftp链接不成功,
ftp.connect({host,user,password,port: 21,"secure": true,"secureOptions": { "rejectUnauthorized": false }})
4. ftp上传文件的时候要带上名字,不然提示无法创建 targetPath + "/" + name
ftp.put(name, targetPath + "/" + name)
用程序解放双手!!!!