Я пытаюсь создать pdf-файл с некоторыми изображениями (в формате datauri) на nodejs, и pdf-файл хранится в моем S3. Ожидается, что возврат функции предоставит URL-адрес s3 файла.
Здесь я использую parse-server для сервера и node-canvas для создания холста изображений, а затем PDFKit для создания pdf из элементов холста. (jsPdf не сработал). Теперь я хочу, чтобы этот PDF-файл был отправлен на мой s3 с помощью AWS-SDK и, наконец, вернул URL-адрес файла. Ниже приведен мой код, который работает до генерации холста. Я не знаю, создается ли pdf или нет в первую очередь, даже до отправки на s3. И о! Все это работает на героку.
Parse.Cloud.define('getBulkMeta',async (req)=>{
const PDFDocument = require('pdfkit'),
{Canvas,loadImage} = require('canvas');
try {
let baseImg = await loadImage('data:image/png;base64,'+req.params.labels[0]);
let labels = req.params.labels,
allCanvas = [],
rowH = baseImg.naturalHeight,
rowW = baseImg.naturalWidth,
perpage = req.params.size[1],
pages = Math.ceil(labels.length/perpage),
imgInd = 0,
g = 10;
size = req.params.size[0];
for(var p=0;p<pages;p++){
let canvas = new Canvas(rowW*((size=='A4')?2:1),rowH*((size=='A4')?2:1)),
ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.rect(0,0,canvas.width,canvas.height)
ctx.fillStyle = "#fff";
ctx.fill();
if(perpage == 1){
let img = await loadImage('data:image/png;base64,'+labels[imgInd++]);
ctx.drawImage(img,g,g,rowW-(2*g),rowH-(2*g));
} else {
var thisImgInd = 0;
for (var r=0;r<2;r++){
for(var c=0;c<2;c++){
let img = await loadImage('data:image/png;base64,'+labels[imgInd++]);
ctx.drawImage(img,g+(c*(rowW-g/2)),g+(r*(rowH-g/2)),rowW-(1.5*g),rowH-(1.5*g));
thisImgInd++
if(thisImgInd>=perpage||imgInd>=labels.length){break;}
}
if(thisImgInd>=perpage||imgInd>=labels.length){break;}
}
}
allCanvas.push(canvas)
}
var thisPDF = new PDFDocument({layout: 'landscape',size:size});
var bcoded;
thisPDF.pipe(()=>{bcoded = new Buffer.from(thisPDF).toString('base64')});
allCanvas.forEach((c,i)=>{
if(i){thisPDF.addPage();}
thisPDF.image(c.toDataURL(),0,0,thisPDF.page.width,thisPDF.page.width);
})
thisPDF.end();
const S3_BUCKET = process.env.S3_BUCKET;
aws.config.region = process.env.AWS_REGION;
aws.config.signatureVersion = 'v4';
let s3 = new aws.S3();
let fileName = req.params.name;
let s3Params = {
Bucket: S3_BUCKET,
Body: bcoded,
Key: fileName,
ContentType : 'application/pdf',
ACL: 'public-read'
};
s3.putObject(s3Params, (err, data) => {
if(err){
console.log('\n\n\n\n\n\n\n'+err+'\n\n\n\n\n\n\n');
throw 'Error: '+ (err);
}
let returnData = {
signedRequest: data,
url: `https://${S3_BUCKET}.s3.amazonaws.com/${fileName}`
};
return (returnData);
})
} catch (e) {throw e;}
})
Обновлять. У меня есть возможность сохранить файл PDF в s3 с помощью следующего кода:
Parse.Cloud.define('getBulkMeta',async (req)=>{
const PDFDocument = require('pdfkit'),
{Canvas,loadImage} = require('canvas');
try {
let baseImg = await loadImage('data:image/png;base64,'+req.params.labels[0]);
let labels = req.params.labels,
allCanvas = [],
rowH = baseImg.naturalHeight,
rowW = baseImg.naturalWidth,
perpage = req.params.size[1],
pages = Math.ceil(labels.length/perpage),
imgInd = 0,
g = 10;
size = req.params.size[0];
for(var p=0;p<pages;p++){
let canvas = new Canvas(),
ctx = canvas.getContext("2d");
canvas.height = rowH*((size=='A4')?2:1);
canvas.width = rowW*((size=='A4')?2:1);
ctx.beginPath();
ctx.rect(0,0,canvas.width,canvas.height)
ctx.fillStyle = "#fff";
ctx.fill();
if(perpage == 1){
let img = await loadImage('data:image/png;base64,'+labels[imgInd++]);
ctx.drawImage(img,g,g,rowW-(2*g),rowH-(2*g));
} else {
var thisImgInd = 0;
for (var r=0;r<2;r++){
for(var c=0;c<2;c++){
let img = await loadImage('data:image/png;base64,'+labels[imgInd++]);
ctx.drawImage(img,g+(c*(rowW-g/2)),g+(r*(rowH-g/2)),rowW-(1.5*g),rowH-(1.5*g));
thisImgInd++
if(thisImgInd>=perpage||imgInd>=labels.length){break;}
}
if(thisImgInd>=perpage||imgInd>=labels.length){break;}
}
}
allCanvas.push(canvas)
}
var thisPDF = new PDFDocument({layout: 'landscape',size:size});
let buffers = [],pdfData,returnData='Hi';
thisPDF.on('data', buffers.push.bind(buffers));
thisPDF.on('end',() => {
pdfData = Buffer.concat(buffers);
const S3_BUCKET = process.env.S3_BUCKET;
aws.config.region = process.env.AWS_REGION;
aws.config.signatureVersion = 'v4';
let s3 = new aws.S3();
let fileName = req.params.name;
let s3Params = {
Bucket: S3_BUCKET,
Body: pdfData,
Key: (+new Date())+'-'+fileName,
ContentType : 'application/pdf',
ACL: 'public-read'
};
s3.putObject(s3Params,(err, data) => {
delete pdfData,thisPDF;
pdfData = null;thisPDF = null;
if(err){ throw 'Error: '+ (err); }
returnData = { signedRequest: data, url: `https://${S3_BUCKET}.s3.amazonaws.com/${fileName}` };
})
})
allCanvas.forEach((c,i)=>{
if(i){thisPDF.addPage();}
thisPDF.image(c.toDataURL(),0,0,{fit:[thisPDF.page.width,thisPDF.page.height]});
})
thisPDF.end();
return returnData;
} catch (e) {throw e;}
})
Однако returnData
всегда выдает «Привет» в качестве вывода, и также кажется, что функция не закрывается - Heroku каждый раз выдает ошибку превышения памяти.