commit
eef194d397
@ -3,6 +3,7 @@
|
|||||||
* 详细设计文档可查看 https://juejin.im/post/5b42d3ede51d4519277b6ce3
|
* 详细设计文档可查看 https://juejin.im/post/5b42d3ede51d4519277b6ce3
|
||||||
*/
|
*/
|
||||||
const util = require('./util');
|
const util = require('./util');
|
||||||
|
const sha1 = require('./sha1');
|
||||||
|
|
||||||
const SAVED_FILES_KEY = 'savedFiles';
|
const SAVED_FILES_KEY = 'savedFiles';
|
||||||
const KEY_TOTAL_SIZE = 'totalSize';
|
const KEY_TOTAL_SIZE = 'totalSize';
|
||||||
@ -40,53 +41,139 @@ export default class Dowloader {
|
|||||||
resolve(url);
|
resolve(url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const fileName = getFileName(url);
|
||||||
if (!lru) {
|
if (!lru) {
|
||||||
// 无 lru 情况下直接判断 临时文件是否存在,不存在重新下载
|
// 无 lru 情况下直接判断 临时文件是否存在,不存在重新下载
|
||||||
wx.getFileInfo({
|
wx.getFileInfo({
|
||||||
filePath: url,
|
filePath: fileName,
|
||||||
success: () => {
|
success: () => {
|
||||||
resolve(url);
|
resolve(url);
|
||||||
},
|
},
|
||||||
fail: () => {
|
fail: () => {
|
||||||
downloadFile(url, lru).then((path) => {
|
if (util.isOnlineUrl(url)) {
|
||||||
resolve(path);
|
downloadFile(url, lru).then((path) => {
|
||||||
}, () => {
|
resolve(path);
|
||||||
reject();
|
}, () => {
|
||||||
});
|
reject();
|
||||||
|
});
|
||||||
|
} else if (util.isDataUrl(url)) {
|
||||||
|
transformBase64File(url, lru).then(path => {
|
||||||
|
resolve(path);
|
||||||
|
}, () => {
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const file = getFile(url);
|
const file = getFile(fileName);
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
// 检查文件是否正常,不正常需要重新下载
|
if (file[KEY_PATH].indexOf('//usr/') !== -1) {
|
||||||
wx.getSavedFileInfo({
|
wx.getFileInfo({
|
||||||
filePath: file[KEY_PATH],
|
filePath: file[KEY_PATH],
|
||||||
success: (res) => {
|
success() {
|
||||||
resolve(file[KEY_PATH]);
|
resolve(file[KEY_PATH]);
|
||||||
},
|
},
|
||||||
fail: (error) => {
|
fail(error) {
|
||||||
console.error(`the file is broken, redownload it, ${JSON.stringify(error)}`);
|
console.error(`base64 file broken, ${JSON.stringify(error)}`);
|
||||||
downloadFile(url, lru).then((path) => {
|
transformBase64File(url, lru).then(path => {
|
||||||
resolve(path);
|
resolve(path);
|
||||||
}, () => {
|
}, () => {
|
||||||
reject();
|
reject();
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
|
} else {
|
||||||
|
// 检查文件是否正常,不正常需要重新下载
|
||||||
|
wx.getSavedFileInfo({
|
||||||
|
filePath: file[KEY_PATH],
|
||||||
|
success: (res) => {
|
||||||
|
resolve(file[KEY_PATH]);
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
console.error(`the file is broken, redownload it, ${JSON.stringify(error)}`);
|
||||||
|
downloadFile(url, lru).then((path) => {
|
||||||
|
resolve(path);
|
||||||
|
}, () => {
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
downloadFile(url, lru).then((path) => {
|
if (util.isOnlineUrl(url)) {
|
||||||
resolve(path);
|
downloadFile(url, lru).then((path) => {
|
||||||
}, () => {
|
resolve(path);
|
||||||
reject();
|
}, () => {
|
||||||
});
|
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) {
|
function downloadFile(url, lru) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
wx.downloadFile({
|
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) => {
|
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({
|
wx.saveFile({
|
||||||
tempFilePath: tempFilePath,
|
tempFilePath: tempFilePath,
|
||||||
success: (fileRes) => {
|
success: (fileRes) => {
|
||||||
@ -229,12 +330,21 @@ function removeFiles(pathsShouldDelete) {
|
|||||||
if (typeof pathDel === 'object') {
|
if (typeof pathDel === 'object') {
|
||||||
delPath = pathDel.filePath;
|
delPath = pathDel.filePath;
|
||||||
}
|
}
|
||||||
wx.removeSavedFile({
|
if (delPath.indexOf('//usr/') !== -1) {
|
||||||
filePath: delPath,
|
wx.getFileSystemManager().unlink({
|
||||||
fail: (error) => {
|
filePath: delPath,
|
||||||
console.error(`removeSavedFile ${pathDel} failed, ${JSON.stringify(error)}`);
|
fail(error) {
|
||||||
},
|
console.error(`removeSavedFile ${pathDel} failed, ${JSON.stringify(error)}`);
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
wx.removeSavedFile({
|
||||||
|
filePath: delPath,
|
||||||
|
fail: (error) => {
|
||||||
|
console.error(`removeSavedFile ${pathDel} failed, ${JSON.stringify(error)}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
97
lib/sha1.js
Normal file
97
lib/sha1.js
Normal 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,
|
||||||
|
}
|
||||||
12
lib/util.js
12
lib/util.js
@ -1,6 +1,14 @@
|
|||||||
|
|
||||||
function isValidUrl(url) {
|
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 = {
|
module.exports = {
|
||||||
isValidUrl,
|
isValidUrl,
|
||||||
|
isOnlineUrl,
|
||||||
|
isDataUrl,
|
||||||
equal
|
equal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -540,9 +540,9 @@ export default class WxCanvas {
|
|||||||
for (const step of realstepList) {
|
for (const step of realstepList) {
|
||||||
this.implementMinaStep(step);
|
this.implementMinaStep(step);
|
||||||
}
|
}
|
||||||
this.ctx.draw(reserve, func);
|
|
||||||
realstepList.length = 0;
|
realstepList.length = 0;
|
||||||
}
|
}
|
||||||
|
this.ctx.draw(reserve, func);
|
||||||
} else if (this.type === "2d") {
|
} else if (this.type === "2d") {
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
this.ctx.clearRect(0, 0, this.canvasNode.width, this.canvasNode.height);
|
this.ctx.clearRect(0, 0, this.canvasNode.width, this.canvasNode.height);
|
||||||
|
|||||||
78
painter.js
78
painter.js
@ -662,49 +662,49 @@ Component({
|
|||||||
|
|
||||||
startPaint() {
|
startPaint() {
|
||||||
this.initScreenK();
|
this.initScreenK();
|
||||||
|
const {
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
} = this.properties.palette;
|
||||||
|
|
||||||
this.downloadImages(this.properties.palette).then(async (palette) => {
|
if (!width || !height) {
|
||||||
const {
|
console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`);
|
||||||
width,
|
return;
|
||||||
height
|
}
|
||||||
} = palette;
|
|
||||||
|
|
||||||
if (!width || !height) {
|
let needScale = false;
|
||||||
console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`);
|
// 生成图片时,根据设置的像素值重新绘制
|
||||||
return;
|
if (width.toPx() !== this.canvasWidthInPx) {
|
||||||
}
|
this.canvasWidthInPx = width.toPx();
|
||||||
|
needScale = this.properties.use2D;
|
||||||
|
}
|
||||||
|
if (this.properties.widthPixels) {
|
||||||
|
setStringPrototype(this.screenK, this.properties.widthPixels / this.canvasWidthInPx)
|
||||||
|
this.canvasWidthInPx = this.properties.widthPixels
|
||||||
|
}
|
||||||
|
|
||||||
let needScale = false;
|
if (this.canvasHeightInPx !== height.toPx()) {
|
||||||
// 生成图片时,根据设置的像素值重新绘制
|
this.canvasHeightInPx = height.toPx();
|
||||||
if (width.toPx() !== this.canvasWidthInPx) {
|
needScale = needScale || this.properties.use2D;
|
||||||
this.canvasWidthInPx = width.toPx();
|
}
|
||||||
needScale = this.properties.use2D;
|
this.setData({
|
||||||
}
|
photoStyle: `width:${this.canvasWidthInPx}px;height:${this.canvasHeightInPx}px;`,
|
||||||
if (this.properties.widthPixels) {
|
}, function () {
|
||||||
setStringPrototype(this.screenK, this.properties.widthPixels / this.canvasWidthInPx)
|
this.downloadImages(this.properties.palette).then(async palette => {
|
||||||
this.canvasWidthInPx = this.properties.widthPixels
|
if (!this.photoContext) {
|
||||||
}
|
this.photoContext = await this.getCanvasContext(this.properties.use2D, 'photo');
|
||||||
|
}
|
||||||
if (this.canvasHeightInPx !== height.toPx()) {
|
if (needScale) {
|
||||||
this.canvasHeightInPx = height.toPx();
|
const scale = getApp().systemInfo.pixelRatio;
|
||||||
needScale = needScale || this.properties.use2D;
|
this.photoContext.width = this.canvasWidthInPx * scale;
|
||||||
}
|
this.photoContext.height = this.canvasHeightInPx * scale;
|
||||||
this.setData({
|
this.photoContext.scale(scale, scale);
|
||||||
photoStyle: `width:${this.canvasWidthInPx}px;height:${this.canvasHeightInPx}px;`,
|
}
|
||||||
|
new Pen(this.photoContext, palette).paint(() => {
|
||||||
|
this.saveImgToLocal();
|
||||||
|
});
|
||||||
|
setStringPrototype(this.screenK, this.properties.scaleRatio);
|
||||||
});
|
});
|
||||||
if (!this.photoContext) {
|
|
||||||
this.photoContext = await this.getCanvasContext(this.properties.use2D, 'photo');
|
|
||||||
}
|
|
||||||
if (needScale) {
|
|
||||||
const scale = getApp().systemInfo.pixelRatio;
|
|
||||||
this.photoContext.width = this.canvasWidthInPx * scale;
|
|
||||||
this.photoContext.height = this.canvasHeightInPx * scale;
|
|
||||||
this.photoContext.scale(scale, scale);
|
|
||||||
}
|
|
||||||
new Pen(this.photoContext, palette).paint(() => {
|
|
||||||
this.saveImgToLocal();
|
|
||||||
});
|
|
||||||
setStringPrototype(this.screenK, this.properties.scaleRatio);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user