20230503 Código de alta calidad para la página de descarga de Javascript pdf

¿Alguna vez te ha molestado el código que escribiste? ¿Alguna vez te has preguntado cómo escribir código de alta calidad? ¡Entonces no te pierdas este tema! Aquí, podemos discutir qué es el código de alta calidad, cómo escribir código de alta calidad y otros temas. Ya sea que sea un desarrollador principiante o senior, puede compartir este tema, obtener inspiración y conocimiento, y mejorar conjuntamente su nivel de programación y eficiencia en el trabajo.

I. Introducción

El código de baja calidad es el peor,
propenso a errores y difícil de mantener.
Errores frecuentes, gran impacto,
baja eficiencia, no estándar,
programación difícil, pensamiento caótico,
alta calidad y
no es nada difícil hacerlo desde cero.

2. Características del código de alta calidad

Estas son algunas características del código de alta calidad:

  1. Gran legibilidad: el código de alta calidad debe ser fácil de leer y comprender. Los nombres, los comentarios y las sangrías claras, así como el diseño estructurado del código, pueden hacer que el código sea más fácil de comprender.

  2. Gran capacidad de mantenimiento: el código de alta calidad debe ser fácil de modificar y expandir. El diseño modular y la refactorización del código pueden hacer que el código sea más fácil de mantener.

  3. Sólida capacidad de prueba: el código de alta calidad debe ser fácil de probar y depurar. El uso de técnicas de prueba, como las pruebas unitarias y las pruebas de integración, puede hacer que el código sea más fácil de probar y depurar.

  4. Alta seguridad: el código de alta calidad debe tener una buena seguridad, y el uso de tecnología de codificación segura y tecnología de prueba de seguridad puede hacer que el código sea más seguro y confiable.

  5. Excelente rendimiento: el código de alta calidad debe tener un buen rendimiento. El uso de estructuras de datos y algoritmos optimizados puede hacer que el código sea más eficiente.

  6. Especificación del código: el código de alta calidad debe cumplir con la especificación del código. La adopción de un estilo de código consistente y hábitos de codificación estandarizados puede hacer que el código sea más fácil de entender y mantener.

  7. Alta reutilización: el código de alta calidad debe tener una buena reutilización. El uso de técnicas como el diseño modular y la programación orientada a objetos puede hacer que el código sea más fácil de reutilizar.

3. Práctica de programación

Aquí hay un código para descargar automáticamente un archivo PDF en una página web usando un script Tampermonkey (o Greasemonkey). Específicamente, este script escucha la página https://copyright.lib.* . .**/pdfindex.jsp.

Los comentarios en el código han explicado las funciones y funciones de cada parte del script con gran detalle, aquí hay una breve introducción:

  • El script primero espera a que la página se cargue por completo para obtener los elementos DOM de la ventana del informe final.
  • El script inserta un botón debajo de la ventana del informe final que inicia la descarga del PDF.
  • Cuando el usuario hace clic en el botón de descarga, el script pasa automáticamente por todas las páginas del PDF y las convierte en un único archivo PDF.
  • Cada página del PDF se guarda en forma de imagen. El script primero obtendrá el enlace de la imagen y luego usará el método $.get() de jQuery para obtener los datos de la imagen. Estos datos se comprimen en codificación base64 en el lado del servidor y se devuelven al cliente en formato JSON.
  • Luego, la secuencia de comandos convierte los datos de la imagen en un formato de blob y los carga en la página mediante un nuevo objeto de imagen. Este paso asegurará que el método jsPDF.addImage() solo se llame una vez, porque este método necesita obtener los datos de la imagen de la URL de la imagen.
  • Luego, la secuencia de comandos agrega el objeto Imagen a jsPDF para que, cuando se agreguen todas las páginas, se guarden como un archivo PDF.

En general, este script utiliza una variedad de técnicas y herramientas, incluidas funciones asíncronas, Promise, MutationObserver, jQuery y jsPDF. Esto hace que el script sea muy eficiente y confiable cuando se manejan múltiples páginas y descargas de imágenes.

Cuarto, el código real

// ==UserScript==
// @name         pdf_downloader
// @namespace    https://blog.rhilip.info/
// @version      1.0
// @description  下载pdf
// @author       DR-ZF-
// @match        https://copyright.lib.****.***.**/pdfindex.jsp*
// @require      https://unpkg.com/[email protected]/dist/jspdf.umd.min.js
// @require      https://unpkg.com/[email protected]/dist/jquery.js
// ==/UserScript==

/* globals $, jspdf */

// 参考油猴NSFC_conclusion_downloader by Rhilip,进行改写
// Copy and edit from https://stackoverflow.com/a/61511955
function waitForElm(selector) {
    
    
    return new Promise(resolve => {
    
    
        if ($(selector).length > 0) {
    
    
            return resolve($(selector));
        }

        const observer = new MutationObserver(mutations => {
    
    
            if ($(selector).length > 0) {
    
    
                resolve($(selector));
                observer.disconnect();
            }
        });

        observer.observe(document.body, {
    
    
            childList: true,
            subtree: true
        });
    });
}

(async function() {
    
    
    'use strict';

    // 等待页面加载
    const conclusionReportTab = await waitForElm('#tool_Zoom');



    // 准备交互按钮,并插入到页面中
    const downloadBtn = $('<button type="button" class="el-button el-button--default el-button--medium is-round">下载全文</button>');
    conclusionReportTab.after(downloadBtn);



    // 点击交互按钮时需要开始下载操作
    downloadBtn.click(async () => {
    
    
        downloadBtn.prop('disabled', true).addClass('is-disabled');
        if (!/无页面/.test(conclusionReportTab.text())) {
    
    
            // 获得项目信息
            const urlParams = new URLSearchParams(location.search);
            const dependUintID = urlParams.get('fid');

            


            // 准备需要的PDF文件,并删除初始页
            const doc = new jspdf.jsPDF();
            doc.deletePage(1);
            doc.setDocumentProperties({
    
    
                title: 'pdf_downloader',
                subject: location.href,
                creator: 'pdf_downloader'
            });

            // 核心下载方法
            const image = new Image();
            for (let i=1;;i++) {
    
    
                downloadBtn.text(`正在下载第 ${
      
      i}`);

                // 获得图片链接
                const response = await $.get('/jumpServlet?', {
    
     page: i, fid: dependUintID });

                console.log(response);
                if (!response){
    
    
                    break; // 此处应该明确为false才break
                }

                const jsonResponse = JSON.parse(response);
                const {
    
     list } = jsonResponse;

                let firstSrc, firstId
                if (Array.isArray(list) && list.length > 0) {
    
    
                    const [firstItem] = list;
                    if (firstItem.src && firstItem.id) {
    
    
                        firstSrc = firstItem.src;
                        firstId = firstItem.id;
                    } else {
    
    
                        console.error(`Unexpected response data. Missing 'src' or 'id' property. Response: ${
      
      JSON.stringify(response)}`);
                    }
                } else {
    
    
                    console.error(`Unexpected response data. 'list' property not found or empty array. Response: ${
      
      JSON.stringify(response)}`);
                }



                // 获得Blob形式的imageData,这样可以防止image.src和jsPDF.addImage会产生两次图片请求,浪费带宽
                // (实际变成了一次请求服务器和两次请求本地blob)
                try {
    
    
                    const imageDataAsBlob = await $.ajax({
    
    
                        url: firstSrc,
                        method: 'GET',
                        xhrFields: {
    
     responseType: 'blob'}
                    });
                    // 加载图片并获得图片的 width, height 属性

                    image.src = URL.createObjectURL(imageDataAsBlob);
                    await image.decode();

                    // 将图片添加进PDF中
                    doc.addPage([image.width, image.height], image.width < image.height ? 'p' : 'l');
                    doc.addImage(image, "PNG", 0, 0, image.width, image.height);
                } catch (e) {
    
    
                    break; // 如果中间有任何失败,则直接break
                }
            }

            // 我们并没法 await 保存过程,所以直接显示下载完成就好,浏览器处理好会自动显示下载文件
            doc.save(`PDF下载.pdf`);
            downloadBtn.text('下载完成');
        }
    });

})();

V. Resumen

La función principal de este código es descargar un archivo PDF desde una página web. Aquí están los puntos buenos:

  1. Se utilizan funciones asíncronas y promesas: el código utiliza asyncfunciones Promisey objetos, de modo que mientras espera operaciones que consumen mucho tiempo, como la carga de la página y la descarga de imágenes, el código puede continuar realizando otras tareas, evitando así el bloqueo o la congelación de la página.

  2. Uso de MutationObserver: el uso de MutationObserver para monitorear los cambios del árbol DOM y luego ejecutar el código posterior cuando aparece el elemento de destino, puede mejorar la velocidad y el rendimiento de carga de la página y evitar errores de ejecución de código causados ​​por la carga lenta de la página.

  3. Alta legibilidad del código: los nombres de variables y funciones son semánticos, los comentarios son claros y claros, la estructura del código es clara y concisa, fácil de entender y mantener.

  4. Uso de las bibliotecas jQuery y jspdf: el código usa la biblioteca jQuery para simplificar la manipulación de DOM y usa la biblioteca jspdf para generar fácilmente archivos PDF.

  5. Manejo adecuado de errores: el código maneja correctamente las solicitudes HTTP y otras situaciones anormales y, al mismo tiempo, finaliza el programa a tiempo cuando ocurre una excepción y proporciona un aviso de error correspondiente para evitar errores graves de ejecución en el código.

Guess you like

Origin blog.csdn.net/weixin_44382195/article/details/130469253