From 0a9a08f8bcbc0bc03cb4e61d97bb9012c131c872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=90=AB=E6=B3=BD?= Date: Fri, 9 Oct 2020 19:45:40 +0800 Subject: [PATCH] =?UTF-8?q?feature=201.=20=E6=94=AF=E6=8C=81=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D=E5=93=88=E5=B8=8C=E5=8C=96=202.=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E9=85=8D=E7=BD=AE=E6=A3=80=E6=B5=8B=203.=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 ++++- dist/index.d.ts | 7 ++- dist/index.js | 98 ++++++++++++++++++++++++----- example/src/App.vue | 10 ++- package.json | 7 ++- src/index.ts | 146 ++++++++++++++++++++++++++++++++++++-------- tsconfig.json | 1 + 7 files changed, 238 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 0867a5c..e831a82 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,14 @@ -# Cmecloud EOS Uploader + -移动云 EOS 浏览器端整合上传工具(当前默认 Bucket 为 gallery),目前限用于完成简单的图片上传 +# EOS Uploader + +EOS 浏览器端整合上传工具(当前默认 Bucket 为 gallery,后续可考虑开放配置),目前限用于完成简单的图片、文件上传 ## usage @@ -19,6 +27,7 @@ const uploader = new Uploader({ secretAccessKey: '您的 Access Key', endpoint: 'Bucket 域名', // 例:eos-beijing-4.cmecloud.cn sslEnabled: true, // 是否开启 https + multiFiles: false, // 是否开启多文件选择 }) ``` @@ -33,4 +42,4 @@ const uploader = new Uploader({ @returns {Promise} ``` -初始化后,直接调用方法即可发起上传流程,返回值为 `Promise`,上传成功后返回可访问文件的 url +初始化后,直接调用方法即可发起上传流程,返回值为 `Promise`,上传成功后返回可访问文件的 url(其中文件名会被哈希加盐散列化,保留原后缀名) diff --git a/dist/index.d.ts b/dist/index.d.ts index d8fddcf..a1e92a8 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -2,7 +2,8 @@ interface UploaderOptions { accessKeyId: string; secretAccessKey: string; endpoint: string; - sslEnabled?: boolean; + sslEnabled: boolean; + multiFiles?: boolean; } declare class Uploader { private _s3?; @@ -12,7 +13,9 @@ declare class Uploader { constructor(options: UploaderOptions); private _createUploader; private _removeUploader; - private _upload; + private _formatFileName; + private _singleUpload; + private _multiUpload; openUploader(): Promise; } export default Uploader; diff --git a/dist/index.js b/dist/index.js index f4bc491..80cfba2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,5 +1,7 @@ import { __awaiter } from "tslib"; import S3 from 'aws-sdk/clients/s3'; +import hash from 'object-hash'; +import dayjs from 'dayjs'; var Access; (function (Access) { Access[Access["private"] = 0] = "private"; @@ -15,29 +17,43 @@ class Uploader { secretAccessKey: '', endpoint: '', sslEnabled: false, + multiFiles: false, }; this._input = undefined; - const currentOptions = Object.assign({}, { + const currentOptions = { apiVersion: '2006‐03‐01', - accessKeyId: '', - secretAccessKey: '', - endpoint: '', + accessKeyId: options.accessKeyId, + secretAccessKey: options.secretAccessKey, + endpoint: options.endpoint, s3ForcePathStyle: true, signatureVersion: 'v2', - sslEnabled: false, - }, options); - this._options = options; + sslEnabled: options.sslEnabled, + }; + const keys = Object.values(currentOptions); + const integrity = keys.some(item => item === '' || item === null || item === undefined); + if (integrity) + throw new Error('请填写完整的配置信息'); + Object.assign(this._options, options); this._s3 = new S3(currentOptions); } _createUploader() { const oldTarget = document.getElementById('file-chooser'); if (oldTarget) { + if (this._options.multiFiles) { + oldTarget.setAttribute('multiple', ''); + } + else { + oldTarget.removeAttribute('multiple'); + } return oldTarget; } const input = window.document.createElement('input'); input.setAttribute('id', 'file-chooser'); input.setAttribute('type', 'file'); input.setAttribute('style', 'visibility: hidden;position: absolute;width: 1px;height: 1px;'); + if (this._options.multiFiles) { + input.setAttribute('multiple', ''); + } document.getElementsByTagName('body')[0].appendChild(input); const target = document.getElementById('file-chooser'); target.addEventListener('click', () => { @@ -52,7 +68,16 @@ class Uploader { } this._input = undefined; } - _upload() { + _formatFileName(file) { + const fileHash = hash({ + name: file.name, + timestamp: dayjs().format('{YYYY} MM-DD HH:mm:ss'), + salt: Math.random(), + }, { algorithm: 'sha1' }); + const fileSuffix = file.name.split('.').slice(-1)[0]; + return { fileHash, fileSuffix }; + } + _singleUpload() { if (!this._input) return Promise.reject('请先构造 Uploader'); const file = this._input.files ? this._input.files[0] : null; @@ -61,8 +86,9 @@ class Uploader { return reject('SDK 加载失败'); const $S = this._s3; if (file) { + const { fileHash, fileSuffix } = this._formatFileName(file); const params = { - Key: file.name, + Key: `${fileHash}.${fileSuffix}`, Bucket: this._bucket, Body: file, ACL: 'public-read', @@ -71,7 +97,7 @@ class Uploader { if (err) { return reject(err); } - return resolve(`${this._options.sslEnabled ? 'https' : 'http'}://${this._options.endpoint}/${this._bucket}/${file.name}`); + return resolve(`${this._options.sslEnabled ? 'https' : 'http'}://${this._options.endpoint}/${this._bucket}/${fileHash}.${fileSuffix}`); }); } else { @@ -79,15 +105,59 @@ class Uploader { } }); } + _multiUpload() { + if (!this._input) + return Promise.reject('请先构造 Uploader'); + const files = this._input.files ? this._input.files : null; + console.log(files); + return new Promise((resolve, reject) => { + if (!this._s3) + return reject('SDK 加载失败'); + const $S = this._s3; + const urls = []; + if (files) { + const filesListLength = files.length; + for (const item of files) { + const { fileHash, fileSuffix } = this._formatFileName(item); + const params = { + Key: `${fileHash}.${fileSuffix}`, + Bucket: this._bucket, + Body: item, + ACL: 'public-read', + }; + $S.putObject(params, (err, data) => { + if (err) { + return reject(err); + } + urls.push(`${this._options.sslEnabled ? 'https' : 'http'}://${this._options.endpoint}/${this._bucket}/${fileHash}.${fileSuffix}`); + if (urls.length === filesListLength) + return resolve(urls); + }); + } + } + else { + return reject('无上传内容'); + } + }); + } openUploader() { return new Promise((resolve, reject) => { this._input = this._createUploader(); this._input.addEventListener('change', (e) => __awaiter(this, void 0, void 0, function* () { e.preventDefault(); - const res = yield this._upload().catch(err => { - this._removeUploader(); - reject(err); - }); + let res; + if (this._options.multiFiles) { + res = yield this._multiUpload().catch(err => { + this._removeUploader(); + reject(err); + }); + } + else { + res = yield this._singleUpload().catch(err => { + this._removeUploader(); + reject(err); + }); + } this._removeUploader(); return resolve(res); }), false); diff --git a/example/src/App.vue b/example/src/App.vue index 1ed0493..9fae954 100644 --- a/example/src/App.vue +++ b/example/src/App.vue @@ -1,3 +1,10 @@ +