Adobe: Generate PDF (HTML to PDF)

Adobe: PDF 生成(HTML to PDF)

This item generates a PDF file from an HTML file, using Adobe PDF Services.

Basic Configs
Step Name
Note
Auto Step icon
Configs for this Auto Step
conf_Auth
C1: OAuth2 Setting *
conf_HtmlDef
C2: Data item that stores the source HTML file *
conf_PageSize
C3: PDF Page Size *
conf_PdfDef
C4: Data item to save the generated PDF file *
conf_DeleteOtherFiles
C5: Delete other files when saving
conf_SaveAs
C6: File name to save as *#{EL}

Notes

Capture

See Also

Script (click to open)
  • An XML file that contains the code below is available to download
    • adobe-html-to-pdf.xml (C) Questetra, Inc. (MIT License)
    • If you are using Professional, you can modify the contents of this file and use it as your own add-on auto step


/** PDF のレイアウト候補 (サイズはインチで指定) */
const LAYOUTS = {
    'A4_P': {
        pageWidth: 8.27,
        pageHeight: 11.69
    },
    'A4_L': {
        pageWidth: 11.69,
        pageHeight: 8.27
    }
};

/**
 * tokenUrl: https://ims-na1.adobelogin.com/ims/token/v3
 * scope: openid, AdobeID, DCAPI
 * @returns {boolean}
 */
const main = () => {
    const authSetting = configs.getObject('conf_Auth');
    const htmlFile = retrieveHtmlFile();
    const pageSize = configs.get('conf_PageSize');
    validateFileName();

    const {uploadUri, assetID} = createAsset(authSetting);
    uploadHtml(uploadUri, htmlFile);
    const statusUrl = htmlToPdf(authSetting, assetID, pageSize);
    engine.saveTemporaryData(statusUrl);

    return proceed();
};

const proceed = () => {
    const authSetting = configs.getObject('conf_Auth');
    const pdfDef = configs.getObject('conf_PdfDef');
    const deleteOtherFiles = configs.getObject('conf_DeleteOtherFiles');
    const fileName = configs.get('conf_SaveAs');
    const statusUrl = engine.restoreTemporaryData();

    return checkStatusAndSaveFile(authSetting, statusUrl, pdfDef, deleteOtherFiles, fileName);
};

/**
 * config から変換元の HTML ファイルを読み出す
 * @returns {QfileView}
 */
const retrieveHtmlFile = () => {
    const htmlDef = configs.getObject('conf_HtmlDef');
    const files = engine.findData(htmlDef);
    if (files === null) {
        throw 'No source file attached.'
    }
    if (files.size() > 1) {
        throw 'More than one source files attached.';
    }
    const sourceFile = files.get(0);
    if (sourceFile.getLength() === 0) {
        throw 'Source file is empty.';
    }
    if (!sourceFile.getContentType().startsWith('text/html')) {
        throw 'Content-Type of the source file is not text/html.';
    }
    return sourceFile;
};

/**
 * config に設定された保存する際のファイル名をバリデーション
 * 空の場合はエラー
 */
const validateFileName = () => {
    const fileName = configs.get('conf_SaveAs');
    if (fileName === '') {
        throw 'File name to save as is blank.';
    }
};

/**
 * asset の作成
 * @param authSetting
 * @returns {any}
 */
const createAsset = (authSetting) => {
    const body = JSON.stringify({
        mediaType: 'text/html' // charset 付きでは指定できない
    });
    const response = httpClient.begin().authSetting(authSetting)
        .header('x-api-key', authSetting.getClientId())
        .body(body, 'application/json')
        .post('https://pdf-services-ue1.adobe.io/assets');
    const status = response.getStatusCode();
    const respStr = response.getResponseAsString();
    if (status !== 200) {
        engine.log(respStr);
        throw `Failed to create asset. status: ${status}`;
    }
    return JSON.parse(respStr);
};

/**
 * HTML ファイルのアップロード
 * @param url
 * @param htmlFile
 */
const uploadHtml = (url, htmlFile) => {
    // Content-Type は asset 作成時の mediaType パラメータ('text/html')と一致させる必要がある
    // body に QfileView をセットすると Content-Type に charset が追加されてしまうため、ByteArrayWrapper をセット
    const response = httpClient.begin()
        .body(fileRepository.readFile(htmlFile), 'text/html')
        .put(url);
    const status = response.getStatusCode();
    if (status !== 200) {
        engine.log(response.getResponseAsString());
        throw `Failed to upload HTML. status: ${status}`;
    }
};

/**
 * HTML から PDF を生成
 * @param authSetting
 * @param assetID
 * @param pageSize
 */
const htmlToPdf = (authSetting, assetID, pageSize) => {
    const body = JSON.stringify({
        assetID,
        json: '{}',
        includeHeaderFooter: false,
        pageLayout: LAYOUTS[pageSize]
    });
    const response = httpClient.begin().authSetting(authSetting)
        .header('x-api-key', authSetting.getClientId())
        .body(body, 'application/json')
        .post('https://pdf-services-ue1.adobe.io/operation/htmltopdf');
    const status = response.getStatusCode();
    if (status !== 201) {
        engine.log(response.getResponseAsString());
        throw `Failed to convert HTML to PDF. status: ${status}`;
    }
    return response.getHeaderValues('Location').get(0);
};

/**
 * PDF 生成のステータスを確認し、完了していればファイルを保存
 * 処理途中であれば false を返す
 * @param authSetting
 * @param statusUrl
 * @param pdfDef
 * @param deleteOtherFiles
 * @param fileName
 * @returns {boolean|undefined} 処理途中であれば false
 */
const checkStatusAndSaveFile = (authSetting, statusUrl, pdfDef, deleteOtherFiles, fileName) => {
    const {status, asset: {downloadUri} = {}, error = {}} = getStatus(authSetting, statusUrl);
    switch (status) {
        case 'done':
            break;
        case 'in progress':
            return false;
        case 'failed':
            engine.log(JSON.stringify(error));
            throw 'Failed to convert HTML to PDF.';
        default:
            throw `The converting status "${status}" is unknown.`;
    }
    const qfile = downloadPdf(downloadUri, fileName);
    saveFile(pdfDef, deleteOtherFiles, qfile);
};

/**
 * 変換ステータスを取得
 * @param authSetting
 * @param statusUrl
 * @returns {Object}
 */
const getStatus = (authSetting, statusUrl) => {
    const response = httpClient.begin().authSetting(authSetting)
        .header('x-api-key', authSetting.getClientId())
        .get(statusUrl);
    const status = response.getStatusCode();
    const respStr = response.getResponseAsString();
    if (status !== 200) {
        engine.log(respStr);
        throw `Failed to get converting status. status: ${status}`;
    }
    return JSON.parse(respStr);
};

/**
 * PDF ファイルのダウンロード
 * @param downloadUrl
 * @param fileName
 */
const downloadPdf = (downloadUrl, fileName) => {
    const response = httpClient.begin().get(downloadUrl);
    const status = response.getStatusCode();
    if (status !== 200) {
        engine.log(response.getResponseAsString());
        throw `Failed to download PDF. status: ${status}`;
    }
    const qfile = new com.questetra.bpms.core.event.scripttask.NewQfile(
        fileName, 'application/pdf', response.getResponse()
    );
    return qfile;
};

/**
 * ファイルを保存
 * @param dataDef
 * @oaram deleteOtherFiles
 * @param qfile
 */
const saveFile = (dataDef, deleteOtherFiles, qfile) => {
    let files = engine.findData(dataDef);
    if (files === null || deleteOtherFiles) {
        files = new java.util.ArrayList();
    }
    files.add(qfile);
    engine.setData(dataDef, files);
};

    
%d bloggers like this: