diff --git a/package-lock.json b/package-lock.json
index 66dd9e3..eade9c7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "qiniuclient",
- "version": "0.5.0",
+ "version": "0.5.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -3916,6 +3916,11 @@
"color-name": "^1.0.0"
}
},
+ "colorful": {
+ "version": "2.1.0",
+ "resolved": "https://registry.nlark.com/colorful/download/colorful-2.1.0.tgz",
+ "integrity": "sha1-aovcvC2kKlDbO0iC+iUmOqofLY4="
+ },
"colormin": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz",
@@ -3944,8 +3949,7 @@
"commander": {
"version": "2.17.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
- "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
- "dev": true
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
},
"commondir": {
"version": "1.0.1",
@@ -4284,6 +4288,11 @@
"resolved": "https://registry.npm.taobao.org/crypt/download/crypt-0.0.2.tgz",
"integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
},
+ "crypto": {
+ "version": "0.0.3",
+ "resolved": "https://registry.nlark.com/crypto/download/crypto-0.0.3.tgz",
+ "integrity": "sha1-RwqBuGvkxe4XrMggeh9TFa4g27A="
+ },
"crypto-browserify": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
@@ -7443,8 +7452,7 @@
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
- "dev": true
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
},
"internal-ip": {
"version": "4.3.0",
@@ -8001,6 +8009,40 @@
"ms": "^2.0.0"
}
},
+ "ks3": {
+ "version": "0.5.1",
+ "resolved": "https://registry.nlark.com/ks3/download/ks3-0.5.1.tgz",
+ "integrity": "sha1-6IOn3ImgfiEykwqC/PbVS5Byx34=",
+ "requires": {
+ "async": "^0.9.0",
+ "colorful": "^2.1.0",
+ "commander": "^2.5.0",
+ "crypto": "0.0.3",
+ "debug": "^2.0.0",
+ "mime": "^1.2.11",
+ "nconf": "^0.6.9",
+ "progress": "^1.1.8",
+ "promptly": "^0.2.0",
+ "urllib": "^2.0.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.9.2",
+ "resolved": "https://registry.nlark.com/async/download/async-0.9.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fasync%2Fdownload%2Fasync-0.9.2.tgz",
+ "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.nlark.com/mime/download/mime-1.6.0.tgz",
+ "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE="
+ },
+ "progress": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npm.taobao.org/progress/download/progress-1.1.8.tgz",
+ "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74="
+ }
+ }
+ },
"latest-version": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
@@ -8864,6 +8906,11 @@
}
}
},
+ "mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.8.tgz",
+ "integrity": "sha1-FjDEKyJR/4HiooPelqVJfqkuXg0="
+ },
"mz": {
"version": "2.7.0",
"resolved": "https://registry.npm.taobao.org/mz/download/mz-2.7.0.tgz",
@@ -8940,6 +8987,23 @@
"xml-char-classes": "^1.0.0"
}
},
+ "nconf": {
+ "version": "0.6.9",
+ "resolved": "https://registry.nlark.com/nconf/download/nconf-0.6.9.tgz",
+ "integrity": "sha1-lXDvFe1vmuays8jV5xtm0xk81mE=",
+ "requires": {
+ "async": "0.2.9",
+ "ini": "1.x.x",
+ "optimist": "0.6.0"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.2.9",
+ "resolved": "https://registry.nlark.com/async/download/async-0.2.9.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fasync%2Fdownload%2Fasync-0.2.9.tgz",
+ "integrity": "sha1-32MGD789Myhqdqr21Vophtn/hhk="
+ }
+ }
+ },
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -9344,6 +9408,15 @@
"is-wsl": "^1.1.0"
}
},
+ "optimist": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npm.taobao.org/optimist/download/optimist-0.6.0.tgz",
+ "integrity": "sha1-aUJIJvNAX3nxQub8PZrljU27kgA=",
+ "requires": {
+ "minimist": "~0.0.1",
+ "wordwrap": "~0.0.2"
+ }
+ },
"optionator": {
"version": "0.8.2",
"resolved": "https://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz",
@@ -10417,6 +10490,14 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true
},
+ "promptly": {
+ "version": "0.2.1",
+ "resolved": "https://registry.nlark.com/promptly/download/promptly-0.2.1.tgz",
+ "integrity": "sha1-ZETnyk29mJnn7rXsOSKCfr3CKzs=",
+ "requires": {
+ "read": "~1.0.4"
+ }
+ },
"proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@@ -10698,6 +10779,14 @@
}
}
},
+ "read": {
+ "version": "1.0.7",
+ "resolved": "https://registry.nlark.com/read/download/read-1.0.7.tgz",
+ "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
+ "requires": {
+ "mute-stream": "~0.0.4"
+ }
+ },
"read-config-file": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-5.0.2.tgz",
@@ -15102,8 +15191,7 @@
"wordwrap": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
- "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
- "dev": true
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
},
"worker-farm": {
"version": "1.7.0",
diff --git a/package.json b/package.json
index c72ccd4..7f9009f 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"electron-json-storage": "^4.1.7",
"fs-extra": "^7.0.1",
"klaw-sync": "^6.0.0",
+ "ks3": "^0.5.1",
"log4js": "^3.0.6",
"mime-types": "^2.1.24",
"multispinner": "^0.2.1",
diff --git a/src/main/index.dev.js b/src/main/index.dev.js
index 1b887c6..8920a1f 100644
--- a/src/main/index.dev.js
+++ b/src/main/index.dev.js
@@ -10,6 +10,7 @@
// Set babel `env` and install `babel-register`
// process.env.NODE_ENV = 'development';
// process.env.BABEL_ENV = 'main';
+import { BrowserWindow } from 'electron';
require("babel-register")({
ignore: /node_modules/
diff --git a/src/renderer/cos/CloudObjectStorage.js b/src/renderer/cos/CloudObjectStorage.js
index 2796e4e..d942745 100644
--- a/src/renderer/cos/CloudObjectStorage.js
+++ b/src/renderer/cos/CloudObjectStorage.js
@@ -9,6 +9,7 @@ import ali from '../cos/ali'
import upyun from '../cos/upyun'
import aws from '../cos/aws'
import jd from '../cos/jd'
+import ks3 from '../cos/ks3'
import brand from '../cos/brand'
@@ -55,6 +56,9 @@ export default class CloudObjectStorage {
case brand.jd.key:
this.cos = jd
break
+ case brand.ks3.key:
+ this.cos = ks3
+ break
case brand.minio.key:
this.cos = aws
break
diff --git a/src/renderer/cos/brand.js b/src/renderer/cos/brand.js
index b1ca441..c189ed1 100644
--- a/src/renderer/cos/brand.js
+++ b/src/renderer/cos/brand.js
@@ -49,6 +49,11 @@ export default {
name: '京东云',
features: ['paging', 'manualPrivateBucket'],
},
+ ks3: {
+ key: 'ks3',
+ name: '金山云',
+ features: ['paging'],
+ },
minio: {
key: 'minio',
name: 'MinIO',
diff --git a/src/renderer/cos/ks3.js b/src/renderer/cos/ks3.js
new file mode 100644
index 0000000..f1bcf10
--- /dev/null
+++ b/src/renderer/cos/ks3.js
@@ -0,0 +1,34 @@
+const KS3 = require('ks3/lib/ks3')
+import KS3Bucket from './ks3Bucket'
+
+let client
+
+function init(param) {
+ client = new KS3(param.access_key, param.secret_key);
+ client.config({
+ dataType: 'json'
+ })
+ console.log('client: ', client)
+}
+
+function getBuckets(callback) {
+ _getBuckets(client, callback)
+}
+
+function _getBuckets(client, callback) {
+ client.service.get(function(error, result) {
+ let data = result.ListAllMyBucketsResult.Buckets
+ data.Bucket.forEach((item, index) => {
+ data.Bucket[index].name = data.Bucket[index].Name
+ data.Bucket[index].region = data.Bucket[index].Region
+ })
+ // 有错误则回调错误
+ callback && callback(error || null, data.Bucket)
+ })
+}
+
+function generateBucket(bucketInfo) {
+ return new KS3Bucket(bucketInfo, client)
+}
+
+export default { init, getBuckets, _getBuckets, generateBucket }
\ No newline at end of file
diff --git a/src/renderer/cos/ks3Bucket.js b/src/renderer/cos/ks3Bucket.js
new file mode 100644
index 0000000..e3f0d84
--- /dev/null
+++ b/src/renderer/cos/ks3Bucket.js
@@ -0,0 +1,183 @@
+import { util } from '../service/index'
+import baseBucket from './baseBucket'
+import brand from './brand'
+
+const fs = require('fs')
+
+class Bucket extends baseBucket {
+ constructor(bucketInfo, cos) {
+ super(bucketInfo, cos, brand.ks3.key)
+ const regionMap = {
+ BEIJING: 'ks3-cn-beijing',
+ SHANGHAI: 'ks3-cn-shanghai',
+ GUANGZHOU: 'ks3-cn-guangzhou',
+ HONGKONG: 'ks3-cn-hk-1',
+ RUSSIA: 'ks3-rus',
+ SINGAPORE: 'ks3-sgp'
+ }
+
+ cos.endpoint = regionMap[bucketInfo.region] + '.ksyuncs.com'
+ cos.config({
+ baseUrl: cos.endpoint
+ })
+ console.log('KS3 BUCKET', this)
+ }
+
+ /**
+ * 获取bucket访问权限
+ * 获取资源
+ * @param vm => page
+ */
+ bindPage(vm) {
+ this.vm = vm
+ this.paging = this.vm.paging
+
+ this.getACL()
+ }
+
+ getACL() {
+ this.cos.bucket.getACL({
+ Bucket: this.name
+ }, (err, data) => {
+ if (err) {
+ console.error("Error", err);
+ } else if (data) {
+ let isPrivate = true
+ const grant = data.AccessControlPolicy.AccessControlList.Grant
+ const grantArray = Array.isArray(grant) ? grant : [grant]
+ grantArray.forEach(item => {
+ if(item.Grantee.URI && item.Grantee.URI.indexOf('AllUsers') !== -1) {
+ isPrivate = false
+ return
+ }
+ })
+ this.setPermission(isPrivate ? 1 : 0);
+ this.getResources();
+ }
+ })
+ }
+
+ createFile(_param, type, callback) {
+ let params = {
+ Bucket: this.name,
+ Key: _param.key,
+ // Body: fs.createReadStream(_param.path),
+ filePath: _param.path,
+ ContentLength: fs.statSync(_param.path).size,
+ }
+ this.cos.object
+ .put(params, function (err, data) {
+ callback(err, { key: _param.key })
+ })
+ }
+
+ // todo 支持批量
+ removeFile(items, callback) {
+ let count = items.length;
+ console.log(items)
+ items.forEach((item) => {
+ let params = {
+ Bucket: this.name,
+ Key: item.Key
+ }
+ this.cos.object.del(params, function(){
+ count = count - 1;
+ console.log(count)
+ if(count === 0) {
+ callback && callback()
+ }
+ })
+ })
+ }
+
+ async renameFile(items, callback) {
+ const item = items[0]
+ this.cos.object.put({
+ Bucket: this.name,
+ Key: item._key // new key
+ }, (err, data) => {
+ if(err) {
+ callback && callback({error: '重命名|创建拷贝失败'})
+ } else {
+ this.cos.object.del({
+ Bucket: this.name,
+ Key: item.Key
+ }, function(err, data){
+ if(err) {
+ callback && callback({error: '重命名|删除旧文件失败'})
+ return
+ }
+ callback && callback()
+ })
+ }
+ }, {
+ 'x-kss-copy-source': `/${this.name}/${item.Key}`
+ })
+ }
+
+ async getResources(option = {}) {
+ await super.preResources()
+ //delimiter
+ let params = {
+ Bucket: this.name,
+ }
+
+ this._handleParams(params, option, {
+ limit: 'max-keys',
+ })
+
+ this.cos.bucket.get(params, (error, data) => {
+ console.log('list objects: ', data)
+ let files = []
+ if(data.ListBucketResult.Contents) {
+ if(!Array.isArray(data.ListBucketResult.Contents)){
+ data.ListBucketResult.Contents = [data.ListBucketResult.Contents]
+ }
+ data.ListBucketResult.Contents.forEach(item => {
+ if (parseInt(item.Size) !== 0) {
+ files.push(util.convertMeta(item, brand.ks3.key))
+ }
+ })
+ }
+
+ data.ListBucketResult.CommonPrefixes && data.ListBucketResult.CommonPrefixes.forEach(item => {
+ files.push(this._getFolder(item.Prefix))
+ })
+
+ this.postResources(
+ {
+ items: files,
+ marker: JSON.parse(data.ListBucketResult.IsTruncated) && data.ListBucketResult.Contents.slice(-1)[0].Key
+ },
+ option
+ )
+ })
+ }
+
+ /**
+ * 返回资源真实链接
+ * @param index
+ * @param key
+ * @param deadline 私有模式,文件有效时间
+ * @returns {*}
+ */
+ generateUrl(key, expires) {
+ let url = `${this.cos.endpoint}/${this.name}/${key}`
+
+ if (this.permission === 1) {
+ // kind of hack
+ const bucketName = this.name;
+ const objectName = encodeURIComponent(key);
+ const ak = this.cos.ak;
+ const sk = this.cos.sk;
+ const deadline = Math.ceil(new Date().getTime()/1000) + expires;
+ const token = encodeURIComponent(this.cos.auth.getQueryStringSignature(sk, deadline, bucketName, objectName))
+
+ url = `http://${this.cos.endpoint}/${bucketName}/${objectName}?AccessKeyId=${ak}&Expires=${deadline}&Signature=` + token
+ }
+
+ return super.generateUrl(url)
+ }
+}
+
+export default Bucket
diff --git a/src/renderer/pages/Login.vue b/src/renderer/pages/Login.vue
index 53c6d26..adcd2c2 100644
--- a/src/renderer/pages/Login.vue
+++ b/src/renderer/pages/Login.vue
@@ -143,6 +143,10 @@
{{ item.name }}->Access Key
+
+ {{ item.name }}->Access Key
+
@@ -199,6 +203,8 @@ export default {
this.regions = Regions.s3
} else if (key === this.brands.jd.key) {
this.regions = Regions.jd
+ } else if (key === this.brands.ks3.key) {
+ this.regions = Regions.ks3
}
},
handleSubmit(key) {
diff --git a/src/renderer/service/util.js b/src/renderer/service/util.js
index 323a399..7493187 100644
--- a/src/renderer/service/util.js
+++ b/src/renderer/service/util.js
@@ -212,6 +212,11 @@ export function convertMeta(item, brandKey = 'qiniu') {
item.fsize = parseInt(item.Size)
item.putTime = new Date(item.LastModified).getTime()
break
+ case brand.ks3.key:
+ item.key = item.Key
+ item.fsize = parseInt(item.Size)
+ item.putTime = new Date(item.LastModified).getTime()
+ break
}
item.mimeType = mime.lookup(item.key) || ''
diff --git a/static/iconfont.css b/static/iconfont.css
index 5ab98e5..7ad94cc 100644
--- a/static/iconfont.css
+++ b/static/iconfont.css
@@ -10,6 +10,10 @@
-moz-osx-font-smoothing: grayscale;
}
+.icon-ks3:before {
+ content: "ks3";
+}
+
.icon-jd:before {
content: "\e701";
}