Adobe PDF Services #成果物: ダウンロード

Adobe PDF Services #成果物: ダウンロード

translate Adobe PDF Services #Results: Download

上流で取得された Polling-URI を用いて成果物ファイル(PDF OPERATIONS の成果 / PDF Services ストレージ内)をダウンロードします。Polling-URI は Jobステータスを返します。Job が処理中(未終了)の場合、ファイル型データ項目は空で更新されます。ダウンロード処理自体がエラーにならない点に注意が必要です。

Auto Step icon
Configs for this Auto Step
AuthzConfU1
U1: PDF-SERVICES-API Client ID 設定を選択してください(認証設定>直接指定) *
AuthzConfU2
U2: PDF-SERVICES-API Client Secret 設定を選択してください(認証設定>直接指定) *
StrConfA1
A1: Polling-URI をセットしてください *#{EL}
SelectConfB0
B0: Jobステータスが格納される文字列型データ項目を選択してください (更新)
SelectConfB1
B1: 成果物ファイルが格納されるファイル型データ項目を選択してください (更新)
StrConfU3
U3: 指定リージョンで処理させたい場合 {regionCode} をセットしてください(”ew1″)#{EL}
SelectConfB1b
B1b: 成果物ファイルが格納されるファイル型データ項目を選択してください (追加)
SelectConfB2
B2: AssetID(s) が格納される文字列型データ項目を選択してください (更新)
SelectConfB3
B3: DownloadUri(s) が格納される文字列型データ項目を選択してください (更新)
StrConfC1
C1: 別名保存したい場合、新しいファイル名をセットしてください#{EL}
Script (click to open)
// Script Example of Business Process Automation
// for 'engine type: 3' ("GraalJS standard mode")
// cf. 'engine type: 2' ("GraalJS Nashorn compatible mode") (renamed from "GraalJS" at 20230526)

//////// START "main()" /////////////////////////////////////////////////////////////////

main();
function main(){ 

////// == Config Retrieving / 工程コンフィグの参照 ==
const strAuthzId          = configs.get( "AuthzConfU1" );       /// REQUIRED
  engine.log( " AutomatedTask Config: Authz ID: " + strAuthzId );
  const strClientId       = httpClient.getOAuth2Token( strAuthzId );
  if (  strClientId     === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {U1: ClientId} is empty \n" );
  }
const strAuthzSecret      = configs.get( "AuthzConfU2" );       /// REQUIRED
  engine.log( " AutomatedTask Config: Authz SECRET: " + strAuthzSecret );
  const strClientSecret   = httpClient.getOAuth2Token( strAuthzSecret );
  if (  strClientSecret === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {U2: ClientSecret} is empty \n" );
  }
const strRegionCode       = configs.get( "StrConfU3" );         // Not Required
  let strRegionPostfix    = strRegionCode !== "" ? ("-" + strRegionCode) : "";
  engine.log( " AutomatedTask Config: strRegionPostfix: " + strRegionPostfix );
  // https://developer.adobe.com/document-services/docs/overview/pdf-services-api/howtos/service-region-configuration-for-apis/
const strPollingUri       = configs.get( "StrConfA1" );         /// REQUIRED

const filesPocketUpdate = configs.getObject( "SelectConfB1" ); // NotRequired
  let filesUpdate       = new java.util.ArrayList();
const filesPocketAppend = configs.getObject( "SelectConfB1b" ); // NotRequired
  let filesAppend       = new java.util.ArrayList();
  if ( filesPocketAppend !== null ) {
    if ( engine.findData( filesPocketAppend ) !== null ) {
      filesAppend       = engine.findData( filesPocketAppend ); // java.util.ArrayList
      engine.log( " AutomatedTask FilesArray {B1b}: " +
                  filesAppend.size() + " files" );
    }
  }
const strPocketStatus      = configs.getObject( "SelectConfB0" );  // Not Required
const strPocketAssetIds    = configs.getObject( "SelectConfB2" );  // Not Required
const strPocketDownUris    = configs.getObject( "SelectConfB3" );  // Not Required
let   strSaveAss           = configs.get( "StrConfC1" );           // NotRequired


////// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)



////// == Calculating / 演算 ==

//// Adobe Developer > PDF Services API > Generate Token
//// Generate access token to perform PDF Services operations
//// https://developer.adobe.com/document-services/docs/apis/#tag/Generate-Token

/// prepare request1
let request1Uri = "https://pdf-services" + strRegionPostfix + ".adobe.io/token";
let request1 = httpClient.begin(); // HttpRequestWrapper
/// prepare application/x-www-form-urlencoded
    request1 = request1.formParam ( "client_id",     strClientId );
    request1 = request1.formParam ( "client_secret", strClientSecret );

/// try request1
const response1     = request1.post( request1Uri ); // HttpResponseWrapper
engine.log( " AutomatedTask ApiRequest1 Start: " + request1Uri );
const response1Code = response1.getStatusCode() + ""; // JavaNum to string
const response1Body = response1.getResponseAsString();
engine.log( " AutomatedTask ApiResponse1 Status: " + response1Code );
if( response1Code !== "200"){
  throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                    response1Code + "\n" + response1Body + "\n" );
}
/* engine.log( response1Body ); // debug
{
  "access_token":"xxxxxxxxxx975yyyyyyyyyy",
  "token_type":"bearer",
  "expires_in":86399
}
*/

/// parse response1 (OAuth Server-to-Server)
const response1Obj = JSON.parse( response1Body );
const strAccessToken = response1Obj.access_token;


//// Adobe Developer > PDF Services API
//// default poll
//// - $.status  // "in progress"(200), "done"(200), "failed"(500)
//// - $.asset.metadata.type
//// - $.asset.downloadUri
//// - $.asset.assetID
//// https://developer.adobe.com/document-services/docs/apis/#tag/Split-PDF/operation/pdfoperations.splitpdf.jobstatus
//// Poll the split pdf job for completion / Poll the pdf to image job for completion
//// - $.status
//// - $.assetList[i].metadata.type
//// - $.assetList[i].downloadUri
//// - $.assetList[i].assetID
//// 
//// Not supported: Poll the accessibility auto-tag job for completion / Poll the extract pdf job for completion / PDF Properties

/// prepare request2
let request2Uri = strPollingUri;
let request2 = httpClient.begin(); // HttpRequestWrapper
/// prepare header parameters
    request2 = request2.bearer ( strAccessToken );
    request2 = request2.header ( "x-api-key", strClientId );

/// try request2
const response2     = request2.get ( request2Uri ); // HttpResponseWrapper
engine.log( " AutomatedTask ApiRequest2 Start: " + request2Uri );
const response2Code = response2.getStatusCode() + ""; // JavaNum to string
const response2Body = response2.getResponseAsString();
engine.log( " AutomatedTask ApiResponse2 Status: " + response2Code );
if( response2Code !== "200"){
  throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                    response2Code + "\n" + response2Body + "\n" );
}
/* engine.log( response2Body ); // debug
{
  "status":"done",
  "asset":{
    "metadata":{
      "type":"application/pdf",
      "size":77322
    },
    "downloadUri":"https://dcplatformstorageservice-prod-us-east-1.s3-accelerate.amazonaws.com/xxxxx838yyyyy",
    "assetID":"urn:aaid:AS:UE1:582675cc-f871-46ab-a21d-fb3ca0e76558"
  }
}
*/

/// parse response2
const response2Obj   = JSON.parse( response2Body );
const strStatus      = response2Obj.status;
engine.log( " AutomatedTask: PDF-Job Status: " + strStatus );
if ( strStatus === "in progress" ) {
  if( strPocketStatus !== null ){
    engine.setData( strPocketStatus,   strStatus );
  }
  if( filesPocketUpdate !== null ){
    engine.setData( filesPocketUpdate, filesUpdate );
  }
  return 0; 
}
if ( strStatus === "failed" ) {
  throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                    response2Code + " (failed)\n" + response2Body + "\n" );
}

let numAssets   = response2Obj.assetList?.length ?? 1;
let arrAssetIds = [];
let arrDownUris = [];
let arrConTypes = [];

if ( "content" in response2Obj && "resource" in response2Obj ){ // case "Extract PDF"
  numAssets = 2;
  arrConTypes.push ( response2Obj.content.metadata.type );
  arrDownUris.push ( response2Obj.content.downloadUri );
  arrAssetIds.push ( response2Obj.content.assetID );
  arrConTypes.push ( response2Obj.resource.metadata.type );
  arrDownUris.push ( response2Obj.resource.downloadUri );
  arrAssetIds.push ( response2Obj.resource.assetID );
} else if ( numAssets === 1 ){
  arrConTypes.push ( response2Obj.asset.metadata.type );
  arrDownUris.push ( response2Obj.asset.downloadUri );
  arrAssetIds.push ( response2Obj.asset.assetID );
} else {
  for ( let i = 0; i < numAssets; i++ ) {
    arrConTypes.push ( response2Obj.assetList[i].metadata.type );
    arrDownUris.push ( response2Obj.assetList[i].downloadUri );
    arrAssetIds.push ( response2Obj.assetList[i].assetID );
  }
}

let arrSaveAss = [];
if ( strSaveAss !== "" ){ 
  arrSaveAss = strSaveAss.split ('\n');
}


const numHttpLimit = httpClient.getRequestingLimit(); // `10` asof 202308
if ( numAssets > numHttpLimit - 2 ){
  numAssets = numHttpLimit - 2;
}

//// GET API call [i]
// Downloading the asset
// https://developer.adobe.com/document-services/docs/overview/pdf-services-api/gettingstarted/#step-5--downloading-the-asset

for ( let i = 0; i < numAssets; i++ ) {
  /// prepare request3
  let request3Uri = arrDownUris[i];
  let request3 = httpClient.begin(); // HttpRequestWrapper
  /// try request3
  const response3     = request3.get ( request3Uri ); // HttpResponseWrapper
  engine.log( " AutomatedTask ApiRequest3 Start: " + request3Uri );
  const response3Code = response3.getStatusCode() + ""; // JavaNum to string
  engine.log( " AutomatedTask ApiResponse3 Status: " + response3Code );
  if( response3Code !== "200"){
    throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                      response3Code + "\n" + response3.getResponseAsString() + "\n" );
  }

  let strTmp = arrSaveAss?.[i] ?? processInstance.getProcessInstanceId().toString() + "-" + i;
    if ( i === 0 ){
      strTmp = arrSaveAss?.[i] ?? processInstance.getProcessInstanceId().toString();
    }
      strTmp = user_correctFileExtension ( strTmp, arrConTypes[i] );

  const qfileTmp = new com.questetra.bpms.core.event.scripttask.NewQfile(
    strTmp, response3.getContentType(), response3.getResponse()
  );
  filesUpdate.add( qfileTmp );
  filesAppend.add( qfileTmp );
}


////// == Data Updating / ワークフローデータへの代入 ==

if( strPocketStatus !== null ){
  engine.setData( strPocketStatus,   strStatus );
}
if( filesPocketUpdate !== null ){
  engine.setData( filesPocketUpdate, filesUpdate );
}
if( filesPocketAppend !== null ){
  engine.setData( filesPocketAppend, filesAppend );
}
if( strPocketAssetIds !== null ){
  engine.setData( strPocketAssetIds, arrAssetIds.join('\n') );
}
if( strPocketDownUris !== null ){
  engine.setData( strPocketDownUris, arrDownUris.join('\n') );
}

} //////// END "main()" /////////////////////////////////////////////////////////////////


// Get the default extension for a content-type (PDF Services targetFormat)
/**
 * Corrects the file extension of the provided save-as name, returns a resultant save-as name with correct extension.
 * If the save-as name does not end with an extension, it appends the correct one according to the MIME type of the content.
 *
 * @param {string} strSaveAs - The name to save the file as. Can be with or without extension.
 * @param {string} strContentType - The MIME type of the content. For example, "application/pdf", "image/jpeg", etc.
 *
 * @returns {string} A corrected save-as name with the correct extension, if needed, according to the content type.
 *
 * @example
 * // returns 'document.pdf'
 * user_correctFileExtension('document', 'application/pdf')
 * 
 * @example
 * // returns 'image.jpg'
 * user_correctFileExtension('image', 'image/jpeg')
 * 
 * @example
 * // returns 'image.jpg' - although 'png' is provided, but jpg image type is given, so it corrects the extension
 * user_correctFileExtension('image.png', 'image/jpeg')
 */
function user_correctFileExtension ( strSaveAs, strContentType ){
  const objMime2Extension = {
    'application/json': '.json',
    'application/pdf': '.pdf',
    'text/html': '.htm',
    'application/zip': '.zip',
    'image/bmp': '.bmp',
    'application/msword': '.doc',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
    'image/gif': '.gif',
    'image/jpeg': '.jpg',
    'image/png': '.png',
    'application/vnd.ms-powerpoint': '.ppt',
    'application/vnd.openxmlformats-officedocument.presentationml.presentation': '.pptx',
    'application/rtf': '.rtf',
    'image/tiff': '.tif',
    'text/plain': '.txt',
    'application/vnd.ms-excel': '.xls',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx'
  };

  let strExtension = objMime2Extension?.[ strContentType ] ?? "";
  if ( ! strSaveAs.endsWith( strExtension ) ){
    strSaveAs += strExtension;
  }
  return strSaveAs;
}


/*
Notes:
- If you place this "Automated Step" in the Workflow diagram, the request will be automatically sent every time the process token arrives.
    - A request is automatically sent to the Adobe PDF Services API server. (REST API)
    - The response from the Adobe PDF Services API server is automatically parsed.
- This "Automated Step" will automatically download the file (Asset) stored in Adobe's internal storage.
    - Default file name is process id.
         - Filename extensions (.pdf, etc.) are autocompleted.
    - In addition to the result files, the Download-URI and AssetID can also be acquired.
- To activate a Workflow App that includes this Automated Step, "HTTP Authz Setting" is required
    - Set Credentials to "Token Fixed Value" in Workflow App.
    - Obtain Credentials ("Client ID" and "Client Secret") in advance.
        - https://acrobatservices.adobe.com/dc-integration-creation-app-cdn/main.html?api=pdf-services-api
    - Adobe Developer Console
        - https://developer.adobe.com/console/projects
- "Results" will be available for download after a certain amount of time.
    - If the job status is `done`, they will be downloaded.
    - If the job status is `in progress`, they can not be downloaded.
        - The FILE type data is updated empty.
    - Place this Automatated Step in the loop flow.
        - Or place it in a position where enough time has passed.

APPENDIX
- PDF Services: 
    - Essential PDF tools to store and share files online, as well as create, combine, export, organize, and fill & sign documents.
    - https://helpx.adobe.com/enterprise/using/optional-services.html
- PDF Services API to automate for your document workflows
    - create a PDF from a dynamic HTML report
    - set a password to prevent unauthorized opening of the document
    - compress it for sharing as an attachment
    - extract text, tables, images and document structure to enable downstream solutions
    - https://developer.adobe.com/document-services/docs/overview/#pdf-services-api-to-automate-for-your-document-workflows
- Adobe PDF Services API Free Tier
    - 500 freeDocument Transactions per month. No credit card required. (asof 202306)
    - https://developer.adobe.com/document-services/docs/overview/limits/#usage-limits
- Internal storage retention period
    - Each ASSET is deleted after a certain period of time.
    - AutomatedTask UnexpectedResponseError: 404
    - `{"error":{"code":"Not Found","message":"The requested resource does not exist."}}`
- Enhanced backward compatibility from "adobe-pdf-services-results-download-2023"
    - Supports Job status storage (B0)
        - To make loop flow easier
        - "B0: Select STRING that stores Job Status (update)"
    - Corresponds to the limit number of HTTP requests (10 times: as of 202308)
        - Files that exceed the limit of the add-on automated step are not downloaded (8 files: as of 202308)
    - Supports "Extract PDF":
        - Get JSON and ZIP

Notes-ja:
- この[自動工程]をワークフロー図に配置すれば、案件が到達する度にリクエストが自動送信されます。
    - Adobe PDF Services API サーバに対してリクエストが自動送出されます。(REST API通信)
    - Adobe PDF Services API サーバからのレスポンスが自動保存解析されます。
- この[自動工程]は、Adobe 内部ストレージに保存されている成果物ファイルを自動ダウンロードします。
    - Defaultファイル名はプロセスIDです。
        - ファイル名の拡張子(.pdf等)は自動補完されます。
    - 成果物ファイル以外に、ファイルの Download-URI AssetID も取得可能です。
- この[アドオン自動工程]を含むワークフローアプリを運用するには[HTTP 認証設定]が必要です。
    - Credentials はワークフローアプリの[トークン直接指定]にセットします。
    - あらかじめ Credentials ("Client ID" および "Client Secret") を取得しておいてください。
        - https://acrobatservices.adobe.com/dc-integration-creation-app-cdn/main.html?api=pdf-services-api
    - Adobe Developer Console
        - https://developer.adobe.com/console/projects
- "成果物" は、一定時間経過後にダウンロードできるようになります。
    - Jobステータスが `done` になっていればダウンロードされます。
    - Jobステータスが `in progress` の間は、ダウンロードされません。
        - ファイル型データは空で更新されます。
    - この[自動工程]の典型的な利用方法としては、ループ構造の中に配置します。
        - もしくは、十分な時間経過が担保される位置に配置します。

APPENDIX-ja
- PDF Servicesとは
    - ファイルのオンラインでの保存、共有のほか、ドキュメントの作成、結合、書き出し、整理、入力と署名を行うための PDF 基本ツールです。
    - https://helpx.adobe.com/jp/enterprise/using/optional-services.html
- Document ワークフローを自動化する PDF Services API
    - 動的 HTML レポートから PDF を簡単に作成
    - ドキュメントが不正に開かれないようにパスワードを設定
    - 添付ファイルとして共有するために圧縮
    - テキスト、表、画像、ドキュメント構造を抽出してダウンストリーム ソリューションを実現
    - https://developer.adobe.com/document-services/docs/overview/#pdf-services-api-to-automate-for-your-document-workflows
- Adobe PDF Services API の無料利用枠
    - 毎月500件の無料ドキュメントトランザクション。クレジットカードは必要なし。(202306現在)
    - https://developer.adobe.com/document-services/docs/overview/limits/#usage-limits
- 内部ストレージの保存期間
    - 各ASSETは、一定時間経過で削除されます。
    - AutomatedTask UnexpectedResponseError: 404
    - `{"error":{"code":"Not Found","message":"The requested resource does not exist."}}`
- 下位互換エンハンス(from "adobe-pdf-services-results-download-2023")
    - Jobステータス格納(B0)に対応
        - ループFlowを組みやすくするため
        - "B0: Jobステータスが格納される文字列型データ項目を選択してください (更新)"
    - HTTPリクエスト数上限に対応(10回:202308現在)
        - アドオン自動工程の制限値を超えるファイルはダウンロードしない(8ファイル:202308現在)
    - "Extract PDF" に対応:
        - JSON と ZIP の取得
        - `https://developer.adobe.com/document-services/docs/apis/#tag/Extract-PDF/operation/pdfoperations.extractpdf.jobstatus`
*/

Download

warning 自由改変可能な JavaScript (ECMAScript) コードです。いかなる保証もありません。
(アドオン自動工程のインストールは Professional editionでのみ可能です)

Notes

  • この[自動工程]をワークフロー図に配置すれば、案件が到達する度にリクエストが自動送信されます。
    • Adobe PDF Services API サーバに対してリクエストが自動送出されます。(REST API通信)
    • Adobe PDF Services API サーバからのレスポンスが自動保存解析されます。
  • この[自動工程]は、Adobe 内部ストレージに保存されている成果物ファイルを自動ダウンロードします。
    • Defaultファイル名はプロセスIDです。
      • ファイル名の拡張子(.pdf等)は自動補完されます。
    • 成果物ファイル以外に、ファイルの Download-URI AssetID も取得可能です。
  • この[アドオン自動工程]を含むワークフローアプリを運用するには[HTTP 認証設定]が必要です。
  • “成果物” は、一定時間経過後にダウンロードできるようになります。
    • Jobステータスが done になっていればダウンロードされます。
    • Jobステータスが in progress の間は、ダウンロードされません。
      • ファイル型データは空で更新されます。
    • この[自動工程]の典型的な利用方法としては、ループ構造の中に配置します。
      • もしくは、十分な時間経過が担保される位置に配置します。

Capture

上流で取得された Polling-URI を用いて成果物ファイル(PDF OPERATIONS の成果 / PDF Services ストレージ内)をダウンロードします。Polling-URI は Jobステータスを返します。Job が処理中(未終了)の場合、ファイル型データ項目は空で更新されます。ダウンロード処理自体がエラーにならない点に注意が必要です。

Appendix

  • PDF Servicesとは
  • Document ワークフローを自動化する PDF Services API
  • Adobe PDF Services API の無料利用枠
  • 内部ストレージの保存期間
    • 各ASSETは、一定時間経過で削除されます。
    • AutomatedTask UnexpectedResponseError: 404
    • {"error":{"code":"Not Found","message":"The requested resource does not exist."}}
  • 下位互換エンハンス(from “adobe-pdf-services-results-download-2023″)
    • Jobステータス格納(B0)に対応
      • ループFlowを組みやすくするため
      • “B0: Jobステータスが格納される文字列型データ項目を選択してください (更新)”
    • HTTPリクエスト数上限に対応(10回:202308現在)
      • アドオン自動工程の制限値を超えるファイルはダウンロードしない(8ファイル:202308現在)
    • “Extract PDF” に対応:
      • JSON と ZIP の取得
      • https://developer.adobe.com/document-services/docs/apis/#tag/Extract-PDF/operation/pdfoperations.extractpdf.jobstatus

See Also

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

%d人のブロガーが「いいね」をつけました。