★★:まあまあ


前回の記事「SPAのWeb APIを使ってみる1 ログインとCookie処理」ではWeb APIを利用するにあたり、必須のユーザ認証とセッション管理についてご説明しました。

今回は他のシステムとの連携を想定し、ファイルをSPAへアーカイブする処理についてご説明いたします。

言語はJavaを前提にしておりますが、他の言語でも仕組みや考え方は同じです。

以下の解説を一通り実装したサンプルを本記事の末尾のリンクよりダウンロードいただけます。

利用API archives_v3

まずはAPIの確認です。

今回は Archives Add(Ver. 3)というAPIを利用します。

詳細は以下マニュアルでご確認ください。

参考(マニュアル):アーカイブ > Archives Add(Ver. 3)

※今回はクラウド/オンプレどちらでも利用できるVer. 3の利用としましたが、機能強化に伴い新たなバージョンのAPIが追加されることがあります。実装時には最新バージョンのAPIを確認してください。


利用にあたりAPIの基本情報は以下の通りです。

URI

http://<hostname>:44230/spa/service/archives_v3  (オンプレ版SPAの場合)

https://<hostname>.spa-cloud.com/spa/service/archives_v3 (SPA Cloudの場合)

HTTPメソッド POST
Content-Typeヘッダー multipart/form-data

次に送信するデータですが、最低限必要なパラメータのみ記載すると以下の通りです。

folderId、pathはどちらか必須になります。今回はpathを利用します。

*folderId 保存先フォルダのID(SPAの画面からフォルダのプロパティを開くことで確認できます)
*path 保存先のパスです(/から記載します。例: /請求書/2022年度)
name アーカイブ時のファイル名
*file 複数指定はできません。アーカイブ処理は、単一ファイルのみが対象です。
ファイル名にマルチバイト文字を含む場合は、文字化けが発生する場合があるため、「name」パラメーターの利用をおすすめします。

まずはHttpURLConnectionの生成から各変数の定義、各ヘッダ情報等をセットします。

/** ベース URL */
private static final String URL_BASE = "https://XXXXXXXX.spa-cloud.com/spa/service";
/** 文書アーカイブ用の URL */
private static final String ARCHIVES_URL = URL_BASE + "/archives_v3";

//アーカイブ処理 START--------------------------------------------------------------------------------------
System.out.println("アーカイブ処理開始");
String path = "/sample";
File file = new File("c:\\sample.pdf");
String name = file.getName();

// HttpURLConnectionの作成
URL urlArchive = new URL(ARCHIVES_URL);
conn = (HttpURLConnection) urlArchive.openConnection();

// HttpURLConnectionの各種設定
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setAllowUserInteraction(false);

SPA Cloudの場合はCSRF対策に対応するため、今回もXSRF-TOKENとX-Requested-Withをセットします。

※詳細は「SPAのWeb APIを使ってみる1 ログインとCookie処理」をご確認ください。

// XSRF-TOKENとX-Requested-Withをセット(リクエストのヘッダに)
conn.setRequestProperty("x-xsrf-token", xsrfToken);
conn.setRequestProperty("x-requested-with", "XMLHttpRequest");

ファイル送信時はマルチパートで送信する必用があるので、マルチパートメッセージを作成します。
パートの区切り文字であるboundary文字列は"----SpaFormBoundary"+カレントミリ秒とします。

String boundary = "----SpaFormBoundary" + Long.toString(System.currentTimeMillis());
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
conn.setRequestProperty("x-requested-with", "XMLHttpRequest");

パラメータの送信 POST用メソッドの定義

パラメータをPOSTするメソッドを作成しておきます。
後でpathとnameパラメータを送信するのに使用します。

/* 改行コード */
private static final String CRLF = "\r\n";

/**
* フォームデータの書き込み処理
*
* @param dos DataOutputStream
* @param boundary boundary文字列
* @param name フィールド名
* @param value 値
* @throws IOException 書き込み処理に失敗した場合
*/
private static void postParam(DataOutputStream dos, String boundary, String name, String value)
throws IOException {
    dos.writeBytes("--" + boundary + CRLF);

    dos.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"" + CRLF);
    dos.writeBytes(CRLF);
    dos.write(value.getBytes(StandardCharsets.UTF_8));
    dos.writeBytes(CRLF);
}

ファイルの送信 POST用メソッドの定義

ローカルにあるファイルを読み取りながら、DataOutputStreamへ書き込んでいきます。

/**
* フォームデータのファイルへの書き込み処理
*
* @param dos DataoutputStream
* @param boundary boundary文字列
* @param name フィールド名
* @param value 値
* @param file 送信するファイル
* @throws IOException 書き込み処理に失敗した場合
*/
private static void postFile(DataOutputStream dos, String boundary, String name, String value, File file)
throws IOException {

    dos.writeBytes("--" + boundary + CRLF);

    StringBuilder sb = new StringBuilder();
    sb.append("Content-Disposition: form-data; ");
    sb.append("name=\"").append(name).append("\"; ");
    sb.append("filename=\"").append(value).append("\"");
    sb.append(CRLF);
    dos.write(sb.toString().getBytes(StandardCharsets.UTF_8));

    dos.writeBytes("Content-Type: application/pdf" + CRLF);
    dos.writeBytes(CRLF);

    // ファイルの書き込み
    try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file))) {
        byte[] buffer = new byte[4096];
        int len = -1;
        while ((len = fis.read(buffer)) != -1) {
            dos.write(buffer, 0, len);
        }
    }
    dos.writeBytes(CRLF);
}

POST処理

作成したpostParam、postFileメソッドを利用してパラメータ、ファイルを送信します。

try (DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(conn.getOutputStream()))) {
    //path 保存先パス指定
    postParam(dos, boundary, "path", path);
    //name ファイル名指定
    postParam(dos, boundary, "name", name);
    //file ファイルデータそのもの送信
    postFile(dos, boundary, "file", file.getName(), file);
    dos.writeBytes("--" + boundary + "--" + CRLF);
}
System.out.println("送信完了");

実装は以上になりますので、動かしてみます。

実行

mainメソッドを呼び出して、実行してみます。

コンソールにはこんな感じの内容が表示されます。

ログイン成功
アーカイブ処理開始
送信完了
アーカイブ成功
ログアウト成功


SPAへアクセスしてみると/sampleフォルダに正常にファイルが登録できていることが確認できますね。

SPAファイルアーカイブ結果

最後に

今回はWeb APIを利用してファイルをアーカイブしてみました。
基幹システムやワークフロー、Webアプリケーションに添付されたファイルをSPAへ登録といった用途等でご利用いただけるのではないでしょうか。

また技術面でも難易度は低く、HTTPやWeb APIのプログラミング経験のある方であれば理解しやすい内容だったのではないかと思います。

今回ご説明した一連の処理を実行できるサンプルのソースファイルを以下のリンクからダウンロードいただけますので参考にしてみてくださいね。

WebApiSampleArchives.javaをダウンロード


※右クリックして「名前を付けてリンク先を保存」等の機能でローカルに保存した上でご確認ください。ファイルの文字コードはUTF-8です。そのまま開くと文字化けして表示される場合があります。

※オンプレ版SPAで利用する場合はXSRF-TOKENの処理はコメントアウトしてご利用ください。

※本記事の情報は、2022年01月14日現在のものです。(SPA V10.6.1 / SPA Cloud Ver.10.6.1.1017)