pdfjs.js 9.82 KB
import * as pdfjs from "pdfjs-dist";
import * as pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

let imgFiles = []
let imgError = []
let imgFinishType = []
let pageNum = 0
//图片缩写至A4至大小比例
const dpiList = {
    "72": { width: 595, height: 842, dpiNum: '72' },
    "96": { width: 794, height: 1123, dpiNum: '96' },
    "100": { width: 833, height: 1186, dpiNum: '100' },
    "120": { width: 1487, height: 2105, dpiNum: '120' },
    "150": { width: 1240, height: 1754, dpiNum: '150' },
    "300": { width: 2480, height: 3508, dpiNum: '300' },
}
//图片质量比例
const canvasQuality = {
    "default": { pageQuality: 1, imgQuality: 0.85 }
}

export function handlePdf(fileItem, pageList = [], customFileName = null, pageScale = 3.5, imgType = "image/jpeg") {
    imgFiles = []
    imgError = []
    pageNum = 0
    imgFinishType = []
    return new Promise((resolve, reject) => {
        let scale = pageScale;
        let file = fileItem
        let fileName = customFileName != null ? customFileName : file.name.split(".")[0];
        let reader = new FileReader();
        reader.readAsDataURL(file); //将文件读取为 DataURL
        reader.onload = () => {
            pdfjs
                .getDocument({
                    url: reader.result,
                    cMapUrl: "./cmaps/",
                    cMapPacked: true,
                }).promise.then((pdf) => {
                    //异常监听
                    pdf._transport.messageHandler.comObj.addEventListener(
                        "error",
                        (event) => {
                            // console.log(event.data);
                            if (event.data.action == "UnsupportedFeature") {
                                imgError.push(`${file.name} Error:UnsupportedFeature`);
                            } else if (event.data.action == "commonobj") {
                                event.data.data.forEach((element) => {
                                    if (element.error) {
                                        imgError.push(`${file.name} Error:commonobj`);
                                    }
                                });
                            }
                        }
                    );

                    pageNum = pdf.numPages
                    console.log("页数:" + pageNum);

                    //准备图片
                    for (let i = 1; i <= pageNum; i++) {
                        let one = i;
                        if (pageList.length > 0 && pageList.includes(i)) {
                            imgFiles.push({ fileName: `${one}_${fileName}.jpg` });
                        } else if (pageList.length == 0) {
                            imgFiles.push({ fileName: `${one}_${fileName}.jpg` });
                        }
                        imgFinishType.push(false)
                    }
                    //处理
                    for (let i = 1; i <= pageNum; i++) {
                        if (imgError.length == 0 && (pageList.length == 0 || pageList.includes(i))) {
                            pdf.getPage(i).then((page) => {
                                const viewport = page.getViewport({ scale: scale });
                                let canvasDom = createCanvas(viewport)
                                page.render({
                                    canvasContext: canvasDom.canvasOption,
                                    viewport,
                                }).promise.then(() => {
                                    let qualitys = canvasQuality['default']
                                    canvasDom.dom.toBlob((blob) => {
                                        let imgFile = new File([blob], imgFiles[i - 1].fileName)
                                        imgHandle(imgFile, i - 1, qualitys.imgQuality).then((imgFile) => {
                                            // console.log(viewport.width, viewport.height)
                                            // console.log((imgFile.size / 1024).toFixed(2))
                                            // console.log(URL.createObjectURL(imgFile));
                                        })
                                    },
                                        imgType,
                                        qualitys.pageQuality
                                    )
                                }).catch((renderError) => {
                                    console.log('renderError', renderError)
                                    imgError.push(`${file.name} Error:${renderError}`)
                                    imgFinishType[i - 1] = true
                                    imgFiles[i - 1].file = null
                                })
                            }).catch(pageError => {
                                console.log(pageError)
                                imgError.push(`${file.name} Error:${pageError}`)
                                imgFinishType[i - 1] = true
                                imgFiles[i - 1].file = null
                            })
                        } else {
                            if (pageList.length == 0) {
                                imgFiles[i - 1].file = null
                            }
                            imgFinishType[i - 1] = true
                        }
                    }
                }).catch((pdfError) => {
                    console.log('pdfError', pdfError)
                    imgError.push(`${file.name} Error:${pdfError ? pdfError.message : ''}`)
                    imgFinishType[0] = true
                })
            let interval = setInterval(() => {
                if ((pageNum != 0 && imgFinishType.length == pageNum) || imgError.length > 0) {
                    let status = true
                    imgFinishType.forEach(type => {
                        !type ? status = false : null
                    })
                    if (status) {
                        clearInterval(interval)
                        resolve({ pdfFile: file, imgFile: imgFiles, pageNum: pageNum, errorType: imgError.length })
                    }
                }
            }, 300);
        }
    })
}

//图片压缩
function imgHandle(file, imgIdx, quality = 0.92, firstType = true, dpiData = dpiList['150'], imgFile = "image/jpeg") {
    return new Promise((resolve, reject) => {
        let fileName = file.name
        let dpi = dpiData
        let reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = () => {
            let img = new Image(); //先创建图片对象
            img.src = reader.result;
            let canvas = document.createElement("canvas");
            let ctx = canvas.getContext("2d");
            img.onload = () => {
                firstType ? dpi = imgDpiOption({ widht: img.width, hieght: img.height }) : null
                let width = 0
                if (img.width < img.height) {
                    width = dpi.width
                } else {
                    width = dpi.height
                }
                canvas.width = width;
                canvas.height = (img.height / img.width) * width;
                ctx.drawImage(img, 0, 0, canvas.width, canvas.height); //绘制图像;把大图片画在一张小画布上,压缩就这么实现了
                canvas.toBlob((blob) => {
                    //超过大小缩小dpi再次进行压缩
                    if (blob.size / 1024 >= 450) {
                        let newDpi = dpiList['100']
                        switch (dpi.dpiNum) {
                            case '300':
                                newDpi = dpiList['120']
                                break;
                            case '120':
                                newDpi = dpiList['150']
                                break;
                            case '150':
                                newDpi = dpiList['100']
                                break;
                            case '100':
                                newDpi = dpiList['96']
                                break;
                            case '96':
                                newDpi = dpiList['96']
                                break;
                            case '72':
                                newDpi = dpiList['100']
                                break
                            default:
                                break;
                        }
                        if (dpi.dpiNum == '100') {
                            console.log(URL.createObjectURL(blob));
                            imgFiles[imgIdx].file = new File([blob], fileName)
                            imgFinishType[imgIdx] = true
                        } else {
                            imgHandle(file, imgIdx, quality, false, newDpi, imgFile)
                        }
                    } else {
                        console.log(URL.createObjectURL(blob));
                        imgFiles[imgIdx].file = new File([blob], fileName)
                        imgFinishType[imgIdx] = true
                    }
                    setTimeout(() => {
                        canvas.remove();
                    }, 200);
                },
                    imgFile,
                    quality
                )
            }
        }
    })
}

//生成pdf预览canvas
function createCanvas(viewport) {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d", {
        willReadFrequently: true,
        alpha: false,
    });
    canvas.style.fontFamily = "sans-serif"
    canvas.style.fontWeight = "700"
    ctx.font = "12px";
    canvas.height = viewport.height;
    canvas.width = viewport.width;

    return { dom: canvas, canvasOption: ctx }
}

//根据图片原图宽度使用合适的dpi数据
function imgDpiOption(viewport) {
    if (viewport.widht > 2000) {
        return dpiList["150"]
    } else {
        return dpiList["100"]
    }
}