From c15cfdfb9934aabc8a34d421168f6f6a2a570322 Mon Sep 17 00:00:00 2001 From: 0JARVIS0 <709406687@qq.com> Date: Thu, 30 Jul 2020 14:42:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81base64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/downloader.js | 89 +++++++++++++++++++++++++++++++++++++------ lib/sha1.js | 97 +++++++++++++++++++++++++++++++++++++++++++++++ lib/util.js | 12 +++++- 3 files changed, 185 insertions(+), 13 deletions(-) create mode 100644 lib/sha1.js diff --git a/lib/downloader.js b/lib/downloader.js index 0c56cc3..ea66a54 100644 --- a/lib/downloader.js +++ b/lib/downloader.js @@ -3,6 +3,7 @@ * 详细设计文档可查看 https://juejin.im/post/5b42d3ede51d4519277b6ce3 */ const util = require('./util'); +const sha1 = require('./sha1'); const SAVED_FILES_KEY = 'savedFiles'; const KEY_TOTAL_SIZE = 'totalSize'; @@ -40,25 +41,34 @@ export default class Dowloader { resolve(url); return; } + const fileName = getFileName(url); if (!lru) { // 无 lru 情况下直接判断 临时文件是否存在,不存在重新下载 wx.getFileInfo({ - filePath: url, + filePath: fileName, success: () => { resolve(url); }, fail: () => { - downloadFile(url, lru).then((path) => { - resolve(path); - }, () => { - reject(); - }); + if (util.isOnlineUrl(url)) { + downloadFile(url, lru).then((path) => { + resolve(path); + }, () => { + reject(); + }); + } else if (util.isDataUrl(url)) { + transformBase64File(url, lru).then(path => { + resolve(path); + }, () => { + reject(); + }); + } }, }) return } - const file = getFile(url); + const file = getFile(fileName); if (file) { // 检查文件是否正常,不正常需要重新下载 @@ -77,16 +87,71 @@ export default class Dowloader { }, }); } else { - downloadFile(url, lru).then((path) => { - resolve(path); - }, () => { - reject(); - }); + if (util.isOnlineUrl(url)) { + downloadFile(url, lru).then((path) => { + resolve(path); + }, () => { + reject(); + }); + } else if (util.isDataUrl(url)) { + transformBase64File(url, lru).then(path => { + resolve(path); + }, () => { + reject(); + }); + } } }); } } +function getFileName(url) { + if (util.isDataUrl(url)) { + const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || []; + const fileName = `${sha1.hex_sha1(bodyData)}.${format}`; + return fileName; + } else { + return url; + } +} + +function transformBase64File(base64data, lru) { + return new Promise((resolve, reject) => { + const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || []; + if (!format) { + console.error('base parse failed'); + reject(); + return; + } + const fileName = `${sha1.hex_sha1(bodyData)}.${format}`; + const path = `${wx.env.USER_DATA_PATH}/${fileName}`; + const buffer = wx.base64ToArrayBuffer(bodyData.replace(/[\r\n]/g, "")); + const result = wx.getFileSystemManager().writeFileSync(path, buffer, 'binary'); + if (!result) { + wx.getFileInfo({ + filePath: path, + success: (tmpRes) => { + const newFileSize = tmpRes.size; + lru ? doLru(newFileSize).then(() => { + saveFile(fileName, newFileSize, path).then((filePath) => { + resolve(filePath); + }); + }, () => { + resolve(path); + }) : resolve(path); + }, + fail: (error) => { + // 文件大小信息获取失败,则此文件也不要进行存储 + console.error(`getFileInfo ${path} failed, ${JSON.stringify(error)}`); + resolve(path); + }, + }); + } else { + reject() + } + }); +} + function downloadFile(url, lru) { return new Promise((resolve, reject) => { wx.downloadFile({ diff --git a/lib/sha1.js b/lib/sha1.js new file mode 100644 index 0000000..e743ec1 --- /dev/null +++ b/lib/sha1.js @@ -0,0 +1,97 @@ +var hexcase = 0; +var chrsz = 8; + +function hex_sha1(s) { + return binb2hex(core_sha1(str2binb(s), s.length * chrsz)); +} + +function core_sha1(x, len) { + x[len >> 5] |= 0x80 << (24 - (len % 32)); + x[(((len + 64) >> 9) << 4) + 15] = len; + + var w = Array(80); + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + var e = -1009589776; + + for (var i = 0; i < x.length; i += 16) { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + var olde = e; + + for (var j = 0; j < 80; j++) { + if (j < 16) w[j] = x[i + j]; + else w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); + var t = safe_add( + safe_add(rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j)) + ); + e = d; + d = c; + c = rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); +} + +function sha1_ft(t, b, c, d) { + if (t < 20) return (b & c) | (~b & d); + if (t < 40) return b ^ c ^ d; + if (t < 60) return (b & c) | (b & d) | (c & d); + return b ^ c ^ d; +} + +function sha1_kt(t) { + return t < 20 + ? 1518500249 + : t < 40 + ? 1859775393 + : t < 60 + ? -1894007588 + : -899497514; +} + +function safe_add(x, y) { + var lsw = (x & 0xffff) + (y & 0xffff); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xffff); +} + +function rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); +} + +function str2binb(str) { + var bin = Array(); + var mask = (1 << chrsz) - 1; + for (var i = 0; i < str.length * chrsz; i += chrsz) + bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - (i % 32)); + return bin; +} + +function binb2hex(binarray) { + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for (var i = 0; i < binarray.length * 4; i++) { + str += + hex_tab.charAt((binarray[i >> 2] >> ((3 - (i % 4)) * 8 + 4)) & 0xf) + + hex_tab.charAt((binarray[i >> 2] >> ((3 - (i % 4)) * 8)) & 0xf); + } + return str; +} + +module.exports = { + hex_sha1, +} \ No newline at end of file diff --git a/lib/util.js b/lib/util.js index 292df2a..a18808d 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,6 +1,14 @@ function isValidUrl(url) { - return /(ht|f)tp(s?):\/\/([^ \\/]*\.)+[^ \\/]*(:[0-9]+)?\/?/.test(url); + return isOnlineUrl(url) || isDataUrl(url); +} + +function isOnlineUrl(url) { + return /(ht|f)tp(s?):\/\/([^ \\/]*\.)+[^ \\/]*(:[0-9]+)?\/?/.test(url) +} + +function isDataUrl(url) { + return /data:image\/(\w+);base64,(.*)/.test(url); } /** @@ -63,6 +71,8 @@ function equal(a, b) { module.exports = { isValidUrl, + isOnlineUrl, + isDataUrl, equal };