Browse Source

Add upload image

zhuzhuyule 8 years ago
parent
commit
dacbc4d752
6 changed files with 238 additions and 14 deletions
  1. 24 2
      app/moe-l10n.js
  2. 1 0
      package.json
  3. 171 9
      views/main/hexo-image.js
  4. 34 0
      views/main/hexo-qiniu.js
  5. 7 0
      views/main/moe-contextmenu.js
  6. 1 3
      views/main/moe-document.js

+ 24 - 2
app/moe-l10n.js

@@ -234,7 +234,18 @@ const strings = {
         "Window": "Window",
         "Window": "Window",
         "Help": "Help",
         "Help": "Help",
         "Toggle Developer Tools": "Toggle Developer Tools",
         "Toggle Developer Tools": "Toggle Developer Tools",
-        "Preference": "Preference"
+        "Preference": "Preference",
+
+        "Upload Finished": "Upload Finished.",
+        "Access Denied.": "Access Denied.",
+        "Upload file count limit.": "Upload file count limit.",
+        "Upload file frequency limit.": "Upload file frequency limit.",
+        "Server error. Upload directory isn't writable.": "Server error. Upload directory isn't writable.",
+        "No files were uploaded.": "No files were uploaded.",
+        "File is empty.": "File is empty.",
+        "File is too large.": "File is too large.(Max: 5M)",
+        "File has an invalid extension.": "File has an invalid extension.",
+        "Could not save uploaded file.": "Could not save uploaded file."
 	},
 	},
     "zh_CN": {
     "zh_CN": {
         "_name": "简体中文",
         "_name": "简体中文",
@@ -371,7 +382,18 @@ const strings = {
         "Window": "窗口",
         "Window": "窗口",
         "Help": "帮助",
         "Help": "帮助",
         "Toggle Developer Tools": "切换开发者工具",
         "Toggle Developer Tools": "切换开发者工具",
-        "Preference": "偏好设置"
+        "Preference": "偏好设置",
+
+        "Upload Finished": "上传完成.",
+        "Access Denied.": "服务器拒绝访问.",
+        "Upload file count limit.": "超出上传文件数量.",
+        "Upload file frequency limit.": "上传文件频率限制.",
+        "Server error. Upload directory isn't writable.": "服务器错误。上传目录不可写.",
+        "No files were uploaded.": "没有文件上传.",
+        "File is empty.": "文件是空的.",
+        "File is too large.": "文件太大.(最大支持5M)",
+        "File has an invalid extension.": "文件扩展名无效.",
+        "Could not save uploaded file.": "无法保存上传的文件."
     },
     },
 	"de": {
 	"de": {
         "_name": "Deutsch",
         "_name": "Deutsch",

+ 1 - 0
package.json

@@ -91,6 +91,7 @@
     "moment-timezone": "^0.5.14",
     "moment-timezone": "^0.5.14",
     "nunjucks": "^3.0.1",
     "nunjucks": "^3.0.1",
     "os-locale": "^1.4.0",
     "os-locale": "^1.4.0",
+    "qiniu": "^7.1.1",
     "raphael": "^2.2.1",
     "raphael": "^2.2.1",
     "strip-indent": "^2.0.0",
     "strip-indent": "^2.0.0",
     "swig": "^1.4.2",
     "swig": "^1.4.2",

+ 171 - 9
views/main/hexo-image.js

@@ -44,6 +44,8 @@ window.md5 = (text) => {
 class ImgManager {
 class ImgManager {
     constructor() {
     constructor() {
         this.fileName = path.basename(hexoWindow.fileName, path.extname(hexoWindow.fileName)) || hexoWindow.ID || "";
         this.fileName = path.basename(hexoWindow.fileName, path.extname(hexoWindow.fileName)) || hexoWindow.ID || "";
+        this.imgPathToUrl = {};
+        this.imgPathToDel = {};
         this.imgMD5IDList = {};
         this.imgMD5IDList = {};
         this.imgPathIDList = {};
         this.imgPathIDList = {};
         this.imgBasePath = '';
         this.imgBasePath = '';
@@ -67,12 +69,15 @@ class ImgManager {
         }
         }
         rootPaht = rootPaht.replace(/\\/g, '/');
         rootPaht = rootPaht.replace(/\\/g, '/');
         if (this.imgBasePath && this.imgBasePath !== rootPaht) {
         if (this.imgBasePath && this.imgBasePath !== rootPaht) {
-            try {
-                fs.renameSync(path.join(this.imgBasePath, this.fileName), path.join(rootPaht, this.fileName));
-            } catch (e) {
-                fs.renameSync(path.join(this.imgBasePath, this.fileName), path.join(rootPaht, this.fileName));
+            const oldPath = path.join(this.imgBasePath, this.fileName);
+            if (fs.existsSync(oldPath)) {
+                try {
+                    fs.renameSync(oldPath, path.join(rootPaht, this.fileName));
+                } catch (e) {
+                    fs.renameSync(oldPath, path.join(rootPaht, this.fileName));
+                }
+                this.updateDictionary(this.imgBasePath, rootPaht)
             }
             }
-            this.updateDictionary(this.imgBasePath, rootPaht)
         }
         }
         this.imgBasePath = rootPaht;
         this.imgBasePath = rootPaht;
     }
     }
@@ -117,6 +122,27 @@ class ImgManager {
         }
         }
     }
     }
 
 
+    getImageOfFile(file) {
+        let imgPath = file.path;
+
+        if (fs.existsSync(imgPath)) {
+            this.upload(file);
+            this.upload(fileb)
+            imgPath = imgPath.replace(/\\/g, '/');
+            let relativePath = '';
+            if (this.imgPathIDList[imgPath]) {
+                relativePath = this.imgPathIDList[imgPath];
+            } else {
+                relativePath = '/' + path.relative(this.imgBasePath, imgPath).replace(/\\/g, '/');
+                this.imgPathIDList[imgPath] = relativePath;
+                if (md5ID) {
+                    this.imgMD5IDList[md5ID] = imgPath;
+                }
+            }
+            return relativePath
+        }
+    }
+
     getImageOfObj(imgObject, imgName, ext) {
     getImageOfObj(imgObject, imgName, ext) {
         if (!ext || ext == '.png') {
         if (!ext || ext == '.png') {
             imgObject = imgObject.toPNG();
             imgObject = imgObject.toPNG();
@@ -132,10 +158,9 @@ class ImgManager {
         if (this.imgMD5IDList[md5ID]) {
         if (this.imgMD5IDList[md5ID]) {
             return this.imgPathIDList[this.imgMD5IDList[md5ID]]
             return this.imgPathIDList[this.imgMD5IDList[md5ID]]
         }
         }
-
+        let imageName = imgName || require('moment')().format('YYYYMMDDhhmmssSSS');
         ext = (ext && this.type[ext.toLowerCase().replace(/^\./, '')]) || '.png';
         ext = (ext && this.type[ext.toLowerCase().replace(/^\./, '')]) || '.png';
 
 
-        let imageName = imgName || require('moment')().format('YYYYMMDDhhmmssSSS');
         let count = 0;
         let count = 0;
         let imageAbsolutePath = path.join(this.imgBasePath, this.fileName, imageName + ext);
         let imageAbsolutePath = path.join(this.imgBasePath, this.fileName, imageName + ext);
         do {
         do {
@@ -162,12 +187,149 @@ class ImgManager {
     }
     }
 
 
     updateDictionary(oldStr, newStr) {
     updateDictionary(oldStr, newStr) {
-        if (this.imgPathIDList.hasOwnProperty()) {
+        if (Object.keys(this.imgPathIDList).length > 0) {
             this.imgPathIDList = JSON.parse(JSON.stringify(this.imgPathIDList).replace(new RegExp(oldStr, 'g'), newStr));
             this.imgPathIDList = JSON.parse(JSON.stringify(this.imgPathIDList).replace(new RegExp(oldStr, 'g'), newStr));
-            if (this.imgMD5IDList.hasOwnProperty())
+            if (Object.keys(this.imgMD5IDList).length > 0)
                 this.imgMD5IDList = JSON.parse(JSON.stringify(this.imgMD5IDList).replace(new RegExp(oldStr, 'g'), newStr));
                 this.imgMD5IDList = JSON.parse(JSON.stringify(this.imgMD5IDList).replace(new RegExp(oldStr, 'g'), newStr));
         }
         }
     }
     }
+
+    uploadDelAll(){
+        Object.keys(this.imgPathToDel).forEach(k=>{
+            imgManager.uploadDel(imgManager.imgPathToDel[k])
+            delete imgManager.imgPathToDel[k];
+        })
+    }
+
+    uploadDel(fileHash){
+        let xhr = new XMLHttpRequest();
+        xhr.open('post', 'https://sm.ms/delete/'+fileHash);
+        xhr.send();
+    }
+
+    upload(file, callback) {
+        let formdata = new FormData();
+        formdata.append('smfile', file);
+        let xhr = new XMLHttpRequest();
+        xhr.open('post', 'https://sm.ms/api/upload');
+        xhr.onreadystatechange = () => {
+            if (xhr.readyState === 4) { // 成功完成
+                // 判断响应结果:
+                if (xhr.status === 200) {
+                    // 成功,通过responseText拿到响应的文本:
+                    if (typeof callback === "function") {
+                        callback(file.name, JSON.parse(xhr.responseText))
+                    }
+                } else {
+                    // 失败,根据响应码判断失败原因:
+                    if (typeof callback === "function") {
+                        callback(file.name, {code: xhr.status})
+                    }
+                }
+            } else {
+                // HTTP请求还在继续...
+            }
+        }
+        xhr.upload.onprogress = (e) => {
+            console.log(Math.floor(100 * e.loaded / e.total) + '%');
+        }
+        xhr.send(formdata)
+    }
+
+    uploadPath(imgPath, callback) {
+        let file = new File([fs.readFileSync(imgPath)], md5(imgPath) + path.extname(imgPath), {type: 'image/' + path.extname(imgPath).slice(1)});
+        return this.upload(file, callback);
+    }
+
+    uploadLocalSrc() {
+        this.isUploading = true;
+        this.timeout = 0;
+
+        let finishedCount = 0;
+        let uploadList = new Map();
+        let successList = new Map();
+        let errorList = new Map();
+
+        function replaceSrc() {
+            let value = editor.getValue();
+            successList.forEach((v, k) => {
+                value = value.replace(new RegExp(imgManager.relativePath(k), 'g'), v.data.url);
+                imgManager.imgPathToUrl[k] = v.data.url;
+                imgManager.imgPathToDel[k] = v.data.hash;
+            })
+
+            editor.setValue(value);
+            hexoWindow.content = value;
+            hexoWindow.changed = true;
+        }
+
+        function uploadEnd(isTimeout) {
+            try {
+                replaceSrc();
+                let errMsg = '';
+                errorList.forEach((v, k) => {
+                    errMsg += k + ':' + __(v) + '</br>';
+                })
+                if (isTimeout) errMsg += 'Upload time out.';
+                if (errMsg) {
+                    window.popMessageShell(null, {
+                        content: errMsg,
+                        type: 'danger',
+                        autoHide: false
+                    })
+                } else {
+                    window.popMessageShell(null, {
+                        content: __('All Files') + ' ' + __('Upload Finished') + ' (' + uploadList.size + ')',
+                        type: 'success',
+                        btnTip: 'check',
+                        autoHide: true
+                    });
+                }
+            } finally {
+                imgManager.isUploading = false;
+            }
+        }
+
+        function checktime(isBreak) {
+            clearTimeout(imgManager.timeout);
+            if (!isBreak)
+                imgManager.timeout = setTimeout(() => {
+                    uploadEnd(true);
+                }, 30000)
+        }
+
+
+        document.querySelector('#right-panel').querySelectorAll('img[localimg="true"]').forEach((item) => {
+            let filePath = item.src.replace(/^file:\/\/\//, '');
+            if (fs.existsSync(filePath)) {
+                uploadList.set(md5(filePath), filePath);
+            } else {
+                errorList.set(filePath, 'No Find File.');
+            }
+        })
+
+        checktime();
+        uploadList.forEach((filepath) => {
+            imgManager.uploadPath(filepath, uploadRequest)
+        })
+
+        function uploadRequest(fileID, response) {
+            finishedCount++;
+            console.log(finishedCount + '/' + uploadList.size)
+            fileID = path.basename(fileID, path.extname(fileID));
+            if (response.code == 'success') {
+                successList.set(uploadList.get(fileID), response)
+            } else {
+                errorList.set(uploadList.get(fileID), response.error)
+            }
+            if (finishedCount >= uploadList.size) {
+                checktime(true);
+                uploadEnd(false);
+                return;
+            }
+            checktime();
+        }
+    }
 }
 }
 
 
 module.exports = ImgManager;
 module.exports = ImgManager;

+ 34 - 0
views/main/hexo-qiniu.js

@@ -0,0 +1,34 @@
+var qiniu = require("qiniu");
+//需要填写你的 Access Key 和 Secret Key
+qiniu.conf.ACCESS_KEY = 'Access_Key';
+qiniu.conf.SECRET_KEY = 'Secret_Key';
+//要上传的空间
+bucket = 'Bucket_Name';
+//上传到七牛后保存的文件名
+key = 'my-nodejs-logo.png';
+//构建上传策略函数,设置回调的url以及需要回调给业务服务器的数据
+function uptoken(bucket, key) {
+    var putPolicy = new qiniu.rs.PutPolicy(bucket+":"+key);
+    putPolicy.callbackUrl = 'http://your.domain.com/callback';
+    putPolicy.callbackBody = 'filename=$(fname)&filesize=$(fsize)';
+    return putPolicy.token();
+}
+//生成上传 Token
+token = uptoken(bucket, key);
+//要上传文件的本地路径
+filePath = './nodejs-logo.png'
+//构造上传函数
+function uploadFile(uptoken, key, localFile) {
+    var extra = new qiniu.io.PutExtra();
+    qiniu.io.putFile(uptoken, key, localFile, extra, function(err, ret) {
+        if(!err) {
+            // 上传成功, 处理返回值
+            console.log(ret.hash, ret.key, ret.persistentId);
+        } else {
+            // 上传失败, 处理返回代码
+            console.log(err);
+        }
+    });
+}
+//调用uploadFile上传
+uploadFile(token, key, filePath);

+ 7 - 0
views/main/moe-contextmenu.js

@@ -111,6 +111,13 @@ document.addEventListener('DOMContentLoaded', () => {
                         window.scrollTogether = !window.scrollTogether;
                         window.scrollTogether = !window.scrollTogether;
                     }
                     }
                 },
                 },
+                {
+                    label: '一键上传',
+                    enabled: !imgManager.isUploading,
+                    click(item, hexoWindow) {
+                        !imgManager.uploadLocalSrc();
+                    }
+                },
                 {
                 {
                     type: moeApp.useHexo ?  'separator' :'normal',
                     type: moeApp.useHexo ?  'separator' :'normal',
                     visible: moeApp.useHexo,
                     visible: moeApp.useHexo,

+ 1 - 3
views/main/moe-document.js

@@ -206,8 +206,6 @@ $(() => {
         }
         }
     );
     );
 
 
-
-
     function replaceImgSelection(codeMirror, title, relativePath) {
     function replaceImgSelection(codeMirror, title, relativePath) {
         codeMirror.replaceSelection(`![${title}](${relativePath})`);
         codeMirror.replaceSelection(`![${title}](${relativePath})`);
     }
     }
@@ -238,7 +236,7 @@ $(() => {
         e.stopPropagation()
         e.stopPropagation()
         e.preventDefault()
         e.preventDefault()
         for (let f of e.dataTransfer.files) {
         for (let f of e.dataTransfer.files) {
-            replaceImgSelection(editor, (editor.getSelection() || ''),imgManager.getImageOfPath(f.path));
+            replaceImgSelection(editor, (editor.getSelection() || ''),imgManager.getImageOfFile(f));
         }
         }
         return false;
         return false;
     }
     }