20230503 Javascript 다운로드 페이지용 고품질 코드 pdf

자신이 작성한 코드 때문에 짜증이 난 적이 있습니까? 고품질 코드를 작성하는 방법에 대해 궁금한 적이 있습니까? 그렇다면 이 주제를 놓치지 마세요! 여기에서 고품질 코드가 무엇인지, 고품질 코드를 작성하는 방법 및 기타 문제에 대해 논의할 수 있습니다. 초보자이든 선임 개발자이든 이 주제에서 공유하고 영감과 지식을 끌어내어 프로그래밍 수준과 작업 효율성을 공동으로 향상시킬 수 있습니다.

I. 소개

품질이 낮은 코드는 최악이고
오류가 발생하기 쉬우며 유지 관리가 어렵습니다.
잦은 버그, 큰 영향,
낮은 효율성, 비표준,
어려운 프로그래밍, 혼란스러운 사고,
높은 품질, 그리고
처음부터 하는 것이 전혀 어렵지 않습니다.

2. 고품질 코드의 특징

다음은 고품질 코드의 몇 가지 특성입니다.

  1. 강력한 가독성: 고품질 코드는 읽고 이해하기 쉬워야 합니다.명확한 이름 지정, 주석 및 들여쓰기는 물론 구조화된 코드 레이아웃으로 코드를 더 쉽게 이해할 수 있습니다.

  2. 강력한 유지보수성: 고품질 코드는 수정 및 확장이 쉬워야 합니다.

  3. 강력한 테스트 가능성: 고품질 코드는 테스트 및 디버그가 쉬워야 합니다. 단위 테스트 및 통합 테스트와 같은 테스트 기술을 사용하면 코드를 더 쉽게 테스트하고 디버그할 수 있습니다.

  4. 높은 보안: 고품질 코드는 보안이 우수해야 하며 보안 코딩 기술과 보안 테스트 기술을 사용하면 코드를 더욱 안전하고 안정적으로 만들 수 있습니다.

  5. 우수한 성능: 고품질 코드는 성능이 좋아야 하며 최적화된 알고리즘과 데이터 구조를 사용하면 코드를 보다 효율적으로 만들 수 있습니다.

  6. 코드 사양: 고품질 코드는 코드 사양을 준수해야 합니다.일관적인 코드 스타일과 표준화된 코딩 습관을 채택하면 코드를 이해하고 유지하기가 더 쉬워집니다.

  7. 높은 재사용성: 고품질 코드는 재사용성이 좋아야 합니다. 모듈식 설계 및 객체 지향 프로그래밍과 같은 기술을 사용하면 코드를 더 쉽게 재사용할 수 있습니다.

3. 프로그래밍 실습

다음은 Tampermonkey(또는 Greasemonkey) 스크립트를 사용하여 웹 페이지에서 PDF 파일을 자동으로 다운로드하는 코드입니다. 특히 이 스크립트는 https://copyright.lib.* .. **/pdfindex.jsp 페이지를 수신합니다.

코드의 주석은 스크립트의 각 부분의 기능과 기능을 매우 자세하게 설명했습니다. 간략한 소개는 다음과 같습니다.

  • 스크립트는 먼저 최종 보고서 창의 DOM 요소를 얻기 위해 페이지가 완전히 로드될 때까지 기다립니다.
  • 스크립트는 PDF 다운로드를 시작하는 최종 보고서 창 아래에 버튼을 삽입합니다.
  • 사용자가 다운로드 버튼을 클릭하면 스크립트가 자동으로 모든 PDF 페이지를 통과하여 단일 PDF 파일로 변환합니다.
  • PDF의 각 페이지는 이미지 형태로 저장되며 스크립트는 먼저 이미지 링크를 얻은 다음 jQuery의 $.get() 메서드를 사용하여 이미지 데이터를 얻습니다. 이 데이터는 서버 측에서 base64 인코딩으로 압축되어 JSON 형식으로 클라이언트에 반환됩니다.
  • 그런 다음 스크립트는 이미지 데이터를 Blob 형식으로 변환하고 새 이미지 개체를 사용하여 페이지에 로드합니다. 이 단계는 jsPDF.addImage() 메서드가 이미지 URL에서 이미지 데이터를 가져와야 하기 때문에 한 번만 호출되도록 합니다.
  • 그런 다음 스크립트는 이미지 개체를 jsPDF에 추가하여 모든 페이지가 추가되면 하나의 PDF 파일로 저장되도록 합니다.

전반적으로 이 스크립트는 비동기 함수, Promise, MutationObserver, jQuery 및 jsPDF를 비롯한 다양한 기술과 도구를 사용합니다. 이것은 여러 페이지와 이미지 다운로드를 처리할 때 스크립트를 매우 효율적이고 안정적으로 만듭니다.

넷째, 실제 코드

// ==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. 요약

이 코드의 주요 기능은 웹 페이지에서 PDF 파일을 다운로드하는 것입니다. 좋은 점은 다음과 같습니다.

  1. 비동기 함수 및 약속이 사용됩니다. 코드는 async함수 Promise와 개체를 사용하므로 페이지 로드 및 이미지 다운로드와 같은 시간 소모적인 작업을 기다리는 동안 코드가 계속해서 다른 작업을 수행할 수 있으므로 페이지 차단 또는 정지를 방지할 수 있습니다.

  2. MutationObserver 사용: MutationObserver를 사용하여 DOM 트리 변경 사항을 모니터링한 다음 대상 요소가 나타날 때 후속 코드를 실행하면 페이지 로딩 속도와 성능을 개선하고 느린 페이지 로딩으로 인한 코드 실행 오류를 피할 수 있습니다.

  3. 높은 코드 가독성: 변수 및 함수 이름은 의미가 있고 주석은 명확하고 명확하며 코드 구조는 명확하고 간결하며 이해하고 유지하기 쉽습니다.

  4. jQuery 및 jspdf 라이브러리 사용: 이 코드는 jQuery 라이브러리를 사용하여 DOM 조작을 단순화하고 jspdf 라이브러리를 사용하여 PDF 파일을 쉽게 생성합니다.

  5. 적절한 오류 처리: 코드는 HTTP 요청 및 기타 비정상적인 상황을 올바르게 처리하고 동시에 예외가 발생하면 프로그램을 종료하고 해당 오류 프롬프트를 제공하여 코드에서 심각한 실행 오류를 방지합니다.

Supongo que te gusta

Origin blog.csdn.net/weixin_44382195/article/details/130469253
Recomendado
Clasificación