由于img.onload方法不同于其他函数,他是一个事件回调。
js是单线程的 他会先按照顺序执行主程序 当主程序执行完成后才会执行事件回调 所以在批量导出图片时onload事件总是最后执行
采用了很多办法 ,网上提供的所有解决办法我都试过了,没有能解决的。所以我将解决方法转到后端来实现,但是node.js默认是单线程,一个node.js应用无法利用多核资源,将网络图片转成base64后再利用exceljs库写到excel中单张图片就需要一秒多的时间,所以最终采用定时器来解决,最近比较忙,就不详细阐述了,代码放下面,有问题直接vx找我(xwx1278039382):
js代码如下:
function main(data, sign, l) {
var timer = setInterval(function () {
var url = data[sign].asin_img;
var img = new Image();
img.src = url;
img.crossOrigin = "*";
if (img.complete == true) {
var base64 = getBase64Image(img);
data[sign].img = base64;
sign++;
computedLong(sign, l)
if (sign >= l) {
clearInterval(timer);
uploadBase(data)
}
}
}, 100)
}
function getBase64Image(img) {//根据网络图片的地址将图片转为base64 nodejs exceljs库需要 如不明白为什么 可以去看一下exceljs的官方文档
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
var dataURL = canvas.toDataURL("image/jpeg"); // 可选其他值 image/jpeg
return dataURL;
}
function uploadBase(data) {
var fileName = getNowFormatDate(time).replace(/\s+/g, "") + (Math.random() * 999).toFixed(0);
$.ajax({
type: "post",
url: "",
data: {
baseData: JSON.stringify(data),
fileName
},
success: function (data) {
if (data.code === 0) {
layer.msg(data.msg)
var a = document.createElement('a');
a.setAttribute('href', "/node_amz/data/" + fileName + ".xlsx");
document.body.appendChild(a);
a.click();//导出完成后 自动下载excel表格到本地
$(".loader-dialog").hide();
} else {
alert("接口异常")
}
},
error: function (err) {
alert("服务异常")
}
})
}
$("#out").click(function () {
var startTime = $("#startTime").val();
var endTime = $("#endTime").val();
var datas = [];
//查询接口
$.ajax({
type: "get",
url: "",
success: function (data) {
$(".loader-dialog").show();
data = JSON.parse(data);
if (data.return_code === 0) {
var prod_info = data.prod_info;
for (var i = 0; i < prod_info.length; i++) {
var asin_info = prod_info[i].asin_info;
for (let j = 0; j < asin_info.length; j++) {
datas.push(asin_info[j])
sessionStorage.setItem("sessionBase", JSON.stringify(datas))
}
}
var sessionBaseData = JSON.parse(sessionStorage.getItem("sessionBase"));
var l = sessionBaseData.length;//导出图片的数量 控制递归函数的执行次数 比较重要
$(".proBefore").text(0)
$(".proAfter").text(l)
main(sessionBaseData, 0, l)//执行
} else {
alert("接口异常")
}
},
error: function (err) {
alert("获取sku异常")
}
})
})
nodejs代码如下:(将代码放到index.js文件)
var express = require("express");
var router = express.Router();
const fs = require("fs");
const Excel = require("exceljs");
var http = require("https");
router.post("/", function (req, res) {
const workbook = new Excel.Workbook();
workbook.created = new Date();
workbook.modified = new Date();
let sheet = workbook.addWorksheet("excel文件名称", {
properties: { defaultRowHeight: 80 },
});
sheet.columns = [
{ header: "id", key: "sku_id", width: 15 },
{ header: "asin", key: "asin", width: 15 },
{ header: "asin_name", key: "asin_name", width: 15 },
{ header: "sku缩略图", key: "sku_img", width: 25 },
];
res.header("Access-Control-Allow-Origin", "*");
var body = req.body.baseData;
var fileName = req.body.fileName;
baseDatas = JSON.parse(body);
sheet.addRows(baseDatas);
function addImg() {
return new Promise((resolve, reject) => {
sheet.eachRow(function (row, rowNumber) {
let rows = sheet.getRow(rowNumber + 1);
rows.height = 80;
rows.eachCell(function (cell, colNumber) {
rows.getCell(colNumber).alignment = {
vertical: "middle",
horizontal: "center",
wrapText: true,
};
});
});
for (var i = 0; i < baseDatas.length; i++) {
var imageId = workbook.addImage({
base64: baseDatas[i].img,
extension: "jpeg",
});
sheet.addImage(imageId, {
tl: { col: 3.5, row: i + 1 + 0.5 },
ext: { width: 80, height: 80 },
});
if (i === baseDatas.length - 1) {
resolve();
}
}
});
}
addImg().then(() => {
var s = "./" + fileName + ".xlsx";
workbook.xlsx.writeFile(s).then(
() => {
res.send({
code: 0,
msg: "导出成功",
});
},
(err) => {
res.send({
code: -1,
msg: "请联系管理员",
});
}
);
});
});
module.exports = router;
里面涉及到的exceljs库的知识直接去官网看一下,链接放这exceljs官网 如果对你有所帮助,记得点个赞哦!