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
| COPYconst fs = require('fs') const path = require('path')
/** 获取上传后图片的预览链接 */ const getPreviewLink = () => { return '' }
/** 获取上传链接 */ const getUploadLink = async () => { return '' } /** 获取上传配置 */ const getUploadConfig = (uploadLink, fileName, file) => { return { method: 'POST', url: uploadLink, headers: { contentType: 'multipart/form-data' }, formData: {/** 上传参数 */} } }
const getImageBuffer = (image) => { let buffer = image.buffer if (!buffer && image.base64Image) { buffer = Buffer.from(image.base64Image, 'base64') }
return new Uint8Array(buffer) }
const getFilePath = (fileName) => { return path.join(__dirname, fileName) }
/** 获取上传文件:先保存本地目录,然后再读取,最后删除本地文件 */ const getFile = async (image) => { const filePath = getFilePath(image.fileName) await fs.writeFileSync(filePath, getImageBuffer(image)) const stream = fs.createReadStream(filePath) setTimeout(() => fs.unlink(getFilePath(image.fileName), () => {}), 100)
return stream }
/** 判断是否上传成功 */ const isUploadSuccess = (data) => { return true }
/** 上传文件 */ const uploadFile = (ctx, config) => { return async image => { try { const uploadLink = getUploadLink() const file = await getFile(image)
const uploadConfig = getUploadConfig(uploadLink, image.fileName, file) return await ctx.Request.request(uploadConfig) } catch (error) { ctx.emit('notification', { title: '上传失败', error }) throw new Error(JSON.stringify(error)) } } }
/** 图片重命名方式 */ const UPDATE_FILE_NAME_ACTION = { time: (file) => { const date = new Date() const hour = `${date.getHours()}`.padStart(2, '0') const minute = `${date.getMinutes()}`.padStart(2, '0') const second = `${date.getSeconds()}`.padStart(2, '0')
return `${hour}${minute}${second}${date.getMilliseconds()}${file.extname}` }, guid: (file) => { let d = new Date().getTime() return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { const r = (d + Math.random() * 16) % 16 | 0 d = Math.floor(d / 16) return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16) }) + file.extname } }
/** 图片重命名 */ const updateFileName = (type, file) => { return type in UPDATE_FILE_NAME_ACTION ? UPDATE_FILE_NAME_ACTION[type](file) : file.fileName }
/** 主函数 */ const handle = async (ctx) => { // 获取 data.json 配置 const config = ctx.getConfig('picBed.wlyd') const upload = uploadFile(ctx, config) for (const key in ctx.output) { const image = ctx.output[key] image.fileName = updateFileName(config.rename_type, image)
const body = await upload(image)
if (isUploadSuccess(body)) { delete ctx.output[key].base64Image delete ctx.output[key].buffer // 更新图片链接,否则 typora 无法正常预览 ctx.output[key].imgUrl = getPreviewLink(image.fileName, config.preview_guid) } } }
/** 界面配置 */ const config = (ctx) => { return [ { name: 'upload_guid', type: 'input', default: '', required: true, alias: '上传GUID' }, { name: 'rename_type', type: 'list', default: 'time', alias: '文件重命名', choices: [ { name: '关闭', value: 'close' }, { name: '时间戳', value: 'time' }, { name: 'GUID', value: 'guid' } ] } ] }
module.exports = (ctx) => { const register = () => { ctx.helper.uploader.register('wlyd', { handle, config }) }
return { uploader: 'wlyd', register } }
|