This commit is contained in:
CPPAlien 2021-06-21 11:13:26 +08:00
commit 40c9453978
4 changed files with 289 additions and 75 deletions

View File

@ -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,27 +41,52 @@ export default class Dowloader {
resolve(url);
return;
}
const fileName = getFileName(url);
if (!lru) {
// 无 lru 情况下直接判断 临时文件是否存在,不存在重新下载
wx.getFileInfo({
filePath: url,
filePath: fileName,
success: () => {
resolve(url);
},
fail: () => {
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) {
if (file[KEY_PATH].indexOf('//usr/') !== -1) {
wx.getFileInfo({
filePath: file[KEY_PATH],
success() {
resolve(file[KEY_PATH]);
},
fail(error) {
console.error(`base64 file broken, ${JSON.stringify(error)}`);
transformBase64File(url, lru).then(path => {
resolve(path);
}, () => {
reject();
});
}
})
} else {
// 检查文件是否正常,不正常需要重新下载
wx.getSavedFileInfo({
filePath: file[KEY_PATH],
@ -76,17 +102,78 @@ export default class Dowloader {
});
},
});
}
} else {
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(url) || [];
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, ""));
wx.getFileSystemManager().writeFile({
filePath: path,
data: buffer,
encoding: 'binary',
success() {
wx.getFileInfo({
filePath: path,
success: (tmpRes) => {
const newFileSize = tmpRes.size;
lru ? doLru(newFileSize).then(() => {
saveFile(fileName, newFileSize, path, true).then((filePath) => {
resolve(filePath);
});
}, () => {
resolve(path);
}) : resolve(path);
},
fail: (error) => {
// 文件大小信息获取失败,则此文件也不要进行存储
console.error(`getFileInfo ${path} failed, ${JSON.stringify(error)}`);
resolve(path);
},
});
},
fail(err) {
console.log(err)
}
})
});
}
function downloadFile(url, lru) {
return new Promise((resolve, reject) => {
wx.downloadFile({
@ -127,8 +214,22 @@ function downloadFile(url, lru) {
});
}
function saveFile(key, newFileSize, tempFilePath) {
function saveFile(key, newFileSize, tempFilePath, isDataUrl = false) {
return new Promise((resolve, reject) => {
if (isDataUrl) {
const totalSize = savedFiles[KEY_TOTAL_SIZE] ? savedFiles[KEY_TOTAL_SIZE] : 0;
savedFiles[key] = {};
savedFiles[key][KEY_PATH] = tempFilePath;
savedFiles[key][KEY_TIME] = new Date().getTime();
savedFiles[key][KEY_SIZE] = newFileSize;
savedFiles['totalSize'] = newFileSize + totalSize;
wx.setStorage({
key: SAVED_FILES_KEY,
data: savedFiles,
});
resolve(tempFilePath);
return;
}
wx.saveFile({
tempFilePath: tempFilePath,
success: (fileRes) => {
@ -229,6 +330,14 @@ function removeFiles(pathsShouldDelete) {
if (typeof pathDel === 'object') {
delPath = pathDel.filePath;
}
if (delPath.indexOf('//usr/') !== -1) {
wx.getFileSystemManager().unlink({
filePath: delPath,
fail(error) {
console.error(`removeSavedFile ${pathDel} failed, ${JSON.stringify(error)}`);
}
})
} else {
wx.removeSavedFile({
filePath: delPath,
fail: (error) => {
@ -236,6 +345,7 @@ function removeFiles(pathsShouldDelete) {
},
});
}
}
}
function getFile(key) {

97
lib/sha1.js Normal file
View File

@ -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,
}

View File

@ -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
};

View File

@ -662,12 +662,10 @@ Component({
startPaint() {
this.initScreenK();
this.downloadImages(this.properties.palette).then(async (palette) => {
const {
width,
height
} = palette;
} = this.properties.palette;
if (!width || !height) {
console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`);
@ -689,7 +687,10 @@ Component({
this.canvasHeightInPx = height.toPx();
needScale = needScale || this.properties.use2D;
}
this.setData({
photoStyle: `width:${this.canvasWidthInPx}px;height:${this.canvasHeightInPx}px;`,
}, function () {
this.downloadImages(this.properties.palette).then(async palette => {
if (!this.photoContext) {
this.photoContext = await this.getCanvasContext(this.properties.use2D, 'photo');
}
@ -699,10 +700,6 @@ Component({
this.photoContext.height = this.canvasHeightInPx * scale;
this.photoContext.scale(scale, scale);
}
this.setData({
photoStyle: `width:${this.canvasWidthInPx}px;height:${this.canvasHeightInPx}px;`,
}, () => {
new Pen(this.photoContext, palette).paint(() => {
this.saveImgToLocal();
});
@ -779,8 +776,8 @@ Component({
wx.canvasToTempFilePath({
canvasId: 'photo',
canvas: that.properties.use2D ? that.canvasNode : null,
destWidth: that.canvasWidthInPx,
destHeight: that.canvasHeightInPx,
destWidth: that.canvasWidthInPx * getApp().systemInfo.pixelRatio,
destHeight: that.canvasHeightInPx * getApp().systemInfo.pixelRatio,
success: function (res) {
that.getImageInfo(res.tempFilePath);
},