DingMing

丁大铭的个人空间,用来分享一些前端小技巧,默默成长吧,哈哈

静态文件上传oss思路

  |  
 阅读次数

OSS简介

阿里云对象存储服务(Object Storage Service,简称OSS),是阿里云对外提供的海量、安全、低成本、高可靠的云存储服务。您可以通过本文档提供的简单的REST接口,在任何时间、任何地点、任何互联网设备上进行上传和下载数据。基于OSS,您可以搭建出各种多媒体分享网站、网盘、个人和企业数据备份等基于大规模数据的服务。

他可以上传静态文件到cdn上

背景

目前的项目打包后生成的静态文件都统一通过 Jenkins 统一上传到了生产服务器去了。现在想将生成文件之间上传的oss cdn上,并替换index.html发布到生产服务器

功能如下

  • 实例化对象 new UploadOss(‘项目名称’)
  • 按日期生成 压缩包(方便追诉)
  • 获取需要上传文件目录,存成数组
  • 获取oss sts token
  • put 按文件目录上传文件
  • 替换index.html内的项目路径成oss地址
  • 删除dist/static文件夹 和对应的.zip文件 减少上传体积

安装配置

yxtnpm i yxt-static-deploy -D
  • 在根目录创建 bin/static-deploy.js 文件
  • package.json 的 scripts 下新增命令 “oss”: “node ./bin/static-deploy.js” 使用
  • 将此命令添加在 build:prod 命令之后

这样就可以在生产环境打包后执行上传操作

使用说明 && 样例

此job作用是 将打包后的 dist/static 文件 上传到oss,并替换index.html文件的相对路径 指向cdn文件

1
2
3
4
5
6
7
8
9
10
11
12
const UploadOss = require('yxt-static-deploy').Put
const UploadOss = require('yxt-static-deploy').Zip // 两种不同的上传方式

const projectName = require('../package.json').name //项目名称

const staticToOss = new UploadOss(projectName) //实例化 并传入 项目名称

staticToOss.zipVersion = ... // 重新设置打包版本
staticToOss.zipPath = ... // 重新设置zip压缩目录

staticToOss.runJob() // 执行上传命令

样例

1
2
3
4
5
6
7
8
9
const UploadOss = require('yxt-static-deploy').Put
const projectName = require('../package.json').name

if (process.env.VUE_APP_APIENV !== 'prod') return console.log('当前VUE_APP_APIENV为:' + process.env.VUE_APP_APIENV)

const staticToOss = new UploadOss(projectName)

staticToOss.runJob()

代码实现

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
const fs = require('fs')
const chalk = require('chalk')
const axios = require('axios')
const AES = require('crypto-js/aes')
const shell = require('shelljs')
const archiver = require('archiver')
const OSS = require('ali-oss')

exports = module.exports = class Zip {
/**
* oss 配置
* */
#userName = '*****'
#pwd = '*****'
#nonceStr = '*****'
#ciphertext = AES.encrypt(this.#pwd, this.#nonceStr).toString()

#stcDomain = '*****'
#OssApiUrl = '*****'

constructor (projectName) {
this.projectName = projectName

this.currentDate = this._dateFormat(new Date())
this.zipVersion = `${this.projectName}_${this.currentDate}.zip`
this.zipPath = `${shell.pwd()}/dist/${this.zipVersion}`
}

/**
* todo 替换static
*/
replaceStatic () {
let distHTML = shell.cat('dist/index.html')

const reg = new RegExp('=static/', 'g')
var newHTML = distHTML.replace(reg, `=${this.#stcDomain}${this.projectName}/static/`)

console.log(chalk.green('static/文件替换完毕...'))
new shell.ShellString(newHTML).to('dist/index.html')
}

/**
* todo 获取文件目录
*/
getList = () => {
const pwd = `${shell.pwd()}/dist/static/`
let tableList = shell.ls(pwd)
let itemList = shell.ls('-R', pwd).filter(function (val) { return tableList.indexOf(val) === -1 })
// itemList = itemList.map(v => `fe-dist/${projectName}/static/${v}`)
return itemList
}

// toZip () {
// console.log(chalk.cyan('压缩文件...'))
// let _this = this
// return new Promise((resolve, reject) => {
// const output = fs.createWriteStream(_this.zipPath)
// const archive = archiver('zip', {
// zlib: { level: 9 }
// })
// archive.pipe(output)

// archive.on('error', (err) => {
// console.error(err)
// })
// archive.directory(`${shell.pwd()}/dist/static/`, `${_this.projectName}/static`)
// resolve({ success: true })
// archive.finalize()
// })
// }

getToken = async () => {
console.log(chalk.cyan('获取token...'), this.#OssApiUrl)
try {
const { data: { token } } = await axios.post(`${this.#OssApiUrl}/login`, {
userName: this.#userName,
pwd: this.#ciphertext
})
console.log('token', chalk.cyan(token))
return token
} catch (error) {
console.log(11, chalk.red(error))
}
}

uploadOss = async () => {
// await this.toZip()
const uploadList = this.getList()
const token = await this.getToken()

if (!token) return Promise.resolve({ success: false })

const { data: { AccessKeyId, AccessKeySecret, SecurityToken, region, bucket } } = await axios({
url: `${this.#OssApiUrl}/sts`,
method: 'get',
headers: { token }
})
const ossClient = new OSS({
accessKeyId: AccessKeyId,
accessKeySecret: AccessKeySecret,
stsToken: SecurityToken,
region,
bucket
})
console.info(chalk.cyan(`${this.zipVersion} 上传OSS...`))
return Promise.all(uploadList.map(async (file) => {
let ossFile = `fe-dist/${this.projectName}/static/${file}`
let localFile = `${shell.pwd()}/dist/static/${file}`
const result = await ossClient.put(ossFile, localFile)
return result
})).then((res) => {
return Promise.resolve({ success: true })
}).catch((e) => {
return Promise.resolve({ success: false })
})
}

runJob = async () => {
if (!this.projectName) return console.log(chalk.red('请输入项目名称'))
const { success } = await this.uploadOss()
if (!success) return console.info(chalk.red('oss 上传失败'))
await this.replaceStatic()

// shell.rm('-rf', `dist/${this.zipVersion}`)
// shell.rm('-rf', `dist/static`)
console.info('End')
}

_dateFormat (date = new Date(), fmt = 'yyyyMMdd-HH_mm_ss') {
date = new Date(date)
let obj = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'H+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
S: date.getMilliseconds() // 毫秒
}
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substring(4 - RegExp.$1.length))
}
for (let key in obj) {
if (new RegExp('(' + key + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? obj[key] : ('00' + obj[key]).substring(('' + obj[key]).length))
}
}
return fmt
}
}