HTML to PDF or PNG
This commit is contained in:
commit
3a5d699c9c
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
.vscode
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
// Olası öznitelikler hakkında bilgi edinmek için IntelliSense kullanın.
|
||||
// Mevcut özniteliklerin açıklamalarını görüntülemek için üzerine gelin.
|
||||
// Daha fazla bilgi için şu adresi ziyaret edin: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug Main Process",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
|
||||
},
|
||||
"args" : ["."],
|
||||
"outputCapture": "std"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
const { app, BrowserWindow } = require('electron');
|
||||
const {randomUUID} = require("node:crypto");
|
||||
const { Command } = require('commander');
|
||||
const express = require('express');
|
||||
const multer = require('multer');
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
function writeFile(ext,data)
|
||||
{
|
||||
let file = randomUUID() + "." + ext;
|
||||
fs.writeFileSync(
|
||||
path
|
||||
.resolve(
|
||||
__dirname,
|
||||
"./output/",
|
||||
file
|
||||
),
|
||||
data
|
||||
);
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{type,website,range,background,size}} options
|
||||
* @returns {Promise<[Buffer,string]>}
|
||||
*/
|
||||
async function generatePDF(options) {
|
||||
const win = new BrowserWindow({
|
||||
webPreferences:{
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
disableDialogs: false,
|
||||
webSecurity: true
|
||||
},
|
||||
show: false,
|
||||
width: options.width,
|
||||
height: options.height
|
||||
});
|
||||
|
||||
|
||||
await new Promise(ok => {
|
||||
win.webContents.addListener("did-finish-load",()=>{
|
||||
ok()
|
||||
});
|
||||
win.webContents.addListener("did-fail-load",()=>{
|
||||
console.error("Hata oluştu")
|
||||
});
|
||||
|
||||
if(options.htmlcontent)
|
||||
{
|
||||
win.loadURL(`data:text/html;base64,${Buffer.from(options.htmlcontent).toString("base64")}`);
|
||||
}else{
|
||||
win.loadURL(options.endpoint);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
let result = await new Promise(result => {
|
||||
switch(options.type)
|
||||
{
|
||||
case "mhtml":{
|
||||
win.webContents.savePage(path.resolve(__dirname, randomUUID() + ".mhtml"),"HTMLOnly");
|
||||
break;
|
||||
}
|
||||
case "image":{
|
||||
win.webContents.setZoomFactor(Math.max(0, Math.min(3.0, options.zoom)))
|
||||
win.webContents.capturePage().then(e => {
|
||||
let binary = e.toPNG();
|
||||
result([binary, "png"]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "pdf":{
|
||||
win.webContents.printToPDF({
|
||||
printBackground: true,
|
||||
displayHeaderFooter: false,
|
||||
scale: options.scale,
|
||||
landscape: options.landscape,
|
||||
pageSize: options.pageSize,
|
||||
pageRanges: options.pageRanges
|
||||
}).then(data => {
|
||||
result([data, "pdf"]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
win.destroy();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
app.disableDomainBlockingFor3DAPIs();
|
||||
app.disableHardwareAcceleration();
|
||||
|
||||
app.addListener("window-all-closed",function(){
|
||||
|
||||
});
|
||||
|
||||
|
||||
async function main()
|
||||
{
|
||||
await new Promise(ok => {
|
||||
app.whenReady().then(() => {
|
||||
ok()
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
let port = express();
|
||||
|
||||
|
||||
port.use(express.static(path.resolve(__dirname,"./output/"),{
|
||||
acceptRanges: true,
|
||||
cacheControl: true,
|
||||
etag: true,
|
||||
lastModified: true
|
||||
}))
|
||||
port.use(express.static(path.resolve(__dirname,"./public/"),{
|
||||
acceptRanges: true,
|
||||
cacheControl: true,
|
||||
etag: true,
|
||||
lastModified: true
|
||||
}))
|
||||
|
||||
port.use(function(request, response, next){
|
||||
response.header("Access-Control-Allow-Origin","*");
|
||||
response.header("Access-Control-Allow-Headers","*");
|
||||
response.header("Access-Control-Allow-Methods","GET, POST, OPTION");
|
||||
next();
|
||||
});
|
||||
|
||||
let memory = multer({storage: multer.memoryStorage()}).none();
|
||||
|
||||
port.post("/pdf", memory,async (request, response) => {
|
||||
|
||||
let {
|
||||
width,
|
||||
height,
|
||||
scale,
|
||||
content: htmlcontent,
|
||||
endpoint,
|
||||
isLandscape,
|
||||
pageSize,
|
||||
pageRanges,
|
||||
output
|
||||
} = request.body;
|
||||
|
||||
output = output || "content";
|
||||
|
||||
let [content, extension] = await generatePDF({
|
||||
htmlcontent,
|
||||
endpoint,
|
||||
type: "pdf",
|
||||
landscape: isLandscape || false,
|
||||
scale: scale || 1.0,
|
||||
width: width || 1920,
|
||||
height: height || 1080,
|
||||
pageSize: pageSize || "A4",
|
||||
range: pageRanges || ""
|
||||
});
|
||||
|
||||
switch(output)
|
||||
{
|
||||
case "json":{
|
||||
let image = writeFile(extension,content);
|
||||
response.json({
|
||||
status: "success",
|
||||
data: image,
|
||||
type: "pdf"
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "json+base64":{
|
||||
response.json({
|
||||
status: "success",
|
||||
data: `data:application/pdf;base64,${content.toString("base64")}`,
|
||||
type: "pdf"
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "content":{
|
||||
response.contentType(extension);
|
||||
response.end(content);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
port.post("/image", memory,async (request, response) => {
|
||||
let {
|
||||
width,
|
||||
height,
|
||||
zoom,
|
||||
content: htmlcontent,
|
||||
endpoint,
|
||||
output
|
||||
} = request.body;
|
||||
|
||||
output = output || "content";
|
||||
|
||||
let [content, extension] = await generatePDF({
|
||||
htmlcontent,
|
||||
endpoint,
|
||||
type: "image",
|
||||
zoom: zoom || 1.0,
|
||||
width: width || 1920,
|
||||
height: height || 1080
|
||||
});
|
||||
|
||||
switch(output)
|
||||
{
|
||||
case "json":{
|
||||
let image = writeFile(extension,content);
|
||||
response.json({
|
||||
status: "success",
|
||||
data: image,
|
||||
type: "image"
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "json+base64":{
|
||||
response.json({
|
||||
status: "success",
|
||||
data: `data:image/png;base64,${content.toString("base64")}`,
|
||||
type: "image"
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "content":{
|
||||
response.contentType(extension);
|
||||
response.end(content);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
port.listen(8473);
|
||||
}
|
||||
process.nextTick(main);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "pdfgenerator",
|
||||
"version": "1.0.0",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "electron . --inspect"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"commander": "^12.1.0",
|
||||
"electron": "^32.1.2",
|
||||
"express": "^4.21.0",
|
||||
"multer": "^1.4.5-lts.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
imagé({
|
||||
input: "htmlcontent",
|
||||
content: "<meta charset=\"UTF-8\"><h1 style='background-color:red;color:White'>This is a PDF</h1>",
|
||||
generate: "pdf",
|
||||
output: "json",
|
||||
success: (data)=> {
|
||||
console.log(data)
|
||||
}
|
||||
});
|
||||
*/
|
||||
async function imagé(options)
|
||||
{
|
||||
if(typeof options != "object")
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
const {
|
||||
input,
|
||||
content,
|
||||
endpoint,
|
||||
generate,
|
||||
output,
|
||||
success,
|
||||
...otheroptions
|
||||
} = options;
|
||||
|
||||
let form = new FormData();
|
||||
|
||||
if(input == "htmlcontent")
|
||||
{
|
||||
if(typeof content != "string" || !content){
|
||||
throw new Error();
|
||||
};
|
||||
|
||||
form.append("content", content)
|
||||
}
|
||||
|
||||
if(input == "endpoint")
|
||||
{
|
||||
if(typeof endpoint != "string" || !endpoint){
|
||||
throw new Error();
|
||||
};
|
||||
|
||||
form.append("endpoint", content)
|
||||
}
|
||||
|
||||
if(generate != "pdf" && generate == "image")
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
switch(output)
|
||||
{
|
||||
case "json":
|
||||
case "json+base64":
|
||||
case "content":{
|
||||
form.append("output", output);
|
||||
break;
|
||||
};
|
||||
default:{
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
for (const name in otheroptions) {
|
||||
const value = otheroptions[name];
|
||||
form.append(name, value);
|
||||
}
|
||||
|
||||
let t = await fetch("http://localhost:8473/" + generate,{
|
||||
method:"post",
|
||||
body: form
|
||||
});
|
||||
|
||||
if(!t.ok)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if(
|
||||
t.headers.get("content-type").indexOf("application/pdf") != -1 ||
|
||||
t.headers.get("content-type").indexOf("image/png") != -1
|
||||
)
|
||||
{
|
||||
let blob = await t.blob(), file;
|
||||
if(generate == "pdf")
|
||||
{
|
||||
file = new File([blob],"File.pdf",{
|
||||
lastModified: new Date(),
|
||||
type:"application/pdf"
|
||||
});
|
||||
}else if(generate == "image"){
|
||||
file = new File([blob],"File.png",{
|
||||
lastModified: new Date(),
|
||||
type:"image/png"
|
||||
});
|
||||
}
|
||||
return (
|
||||
typeof options.success == "function" &&
|
||||
options.success(file),
|
||||
file
|
||||
);
|
||||
}else{
|
||||
let data = await t.json();
|
||||
return (
|
||||
typeof options.success == "function" &&
|
||||
options.success(data),
|
||||
data
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue