0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[intra-mart] IM-LogicDesignerからS3 Presigned URLを用いたファイルアップロード

Posted at

はじめに

NTTデータ イントラマートにはIM-LogicDeignerという、intra-mart Accel Platform上でビジネスロジックをローコードで簡単に作成できるアプリケーションが提供されています。作成したロジックはREST APIとして利用可能です。

今回このIM-LogicDesignerを使って、AWSのS3 Presigned URLを用いたファイルアップロードする方法を紹介します。

S3 Presigned URL(署名付きURL)とは

S3 Presigned URL(署名付きURL)は、バケットポリシーを更新せずに一時的にS3内のオブジェクトへアクセスが可能となる署名付きのURLです。署名付きURLを使用することによって、AWS のセキュリティ認証情報やアクセス許可を持たずに、一時的にファイルのアップロードやダウンロードすることが可能となります。

今回は、IM-LogicDesignerからS3 Presigned URLを使って、S3へファイルアップロードしようとした際に問題となった点と、その解決方法について解説します。

背景

今回は、以下の流れでファイルをCSVファイルをアップロードしてみます。

実際のPresigned URLの生成はAWS LambdaからBoto3を使って、以下のような形で生成します。

import boto3
s3 = boto3.client("s3")
upload_url = s3.generate_presigned_url(
    ClientMethod = "put_object",
    Params = {
        'Bucket': "bucket_name",
        'Key': "object_key"
    },
    ExpiresIn = 500,
    HttpMethod = "PUT"
)

通常はParamsパラメータにContent-TYpeを指定しますが、今回はこれが省略されていました。複数のContent-Typeを許容する目的でPresigned URL生成時にContent-Typeが指定されないということもあるかと思いますが、Presigned URLを使ってファイルアップロードする際には、Content-Typeが一致しないと受け付けません。つまり、この場合はファイルアップロード時にContent-Typeを省略する必要が出てきます。業務サーバ側の処理を変更すれば良いのですが、今回はIM-LogicDesignerからContent-Typeを省略したアクセスができる方法を試してみます。

問題点

まずはIM-LogicDesignerでHTTP通信を行う際の利用頻度の高い「ユーザ定義編集 - REST」の仕様を確認してみます。

リクエスト時にContent-Typeを指定する項目はなく、状況に合わせて自動付与される仕様です。
以下の条件を満たす場合にはContent-Typeの自動付与は行われませんが、今回はCSVファイルのアップロードをする目的ですので合致しません。

  • リクエスト種別:raw
  • 入力値の body パラメータの型:binary または byte[]

次に、HttpClientオブジェクトを用いた通信の仕様を確認します。

Content-Type省略時には以下の条件によってContent-Typeが指定される仕様です。

  • 非マルチパート時:application/x-www-form-urlencoded
  • マルチパート時:multipart/form-data

以上の点から、intra-martの標準機能ではIM-LogicDesignerから外部へのHTTP通信時にContent-Typeの指定を省略することはできない、ということになります。

対処方法

intra-martの標準機能では実現できないことがわかったので、IM-LogicDesigner の拡張機能を利用し独自のJavaタスクを生成する方法で対処します。

まずはJavaでContent-Typeを省略したHTTP通信の動作検証を行います。

   public static void uploadFile(String targetUrl, File file) throws IOException {
       // URLオブジェクトを作成
       URL url = new URL(targetUrl);
       HttpURLConnection connection = (HttpURLConnection) url.openConnection();
       // 接続設定
       connection.setDoOutput(true);
       connection.setRequestMethod("PUT");
       connection.setRequestProperty("Content-Length", String.valueOf(file.length()));

       // ファイルをストリームとして送信
       try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
            FileInputStream fileInputStream = new FileInputStream(file)) {
           byte[] buffer = new byte[4096];
           int bytesRead;
           while ((bytesRead = fileInputStream.read(buffer)) != -1) {
               outputStream.write(buffer, 0, bytesRead);
           }
           outputStream.flush();
       }
       // レスポンスコードを取得
       int responseCode = connection.getResponseCode();
       System.out.println("Response Code: " + responseCode);
       // 接続を切断
       connection.disconnect();
   }

この方法で無事にファイルアップロードできました。ポイントは、curl -X PUT --upload-file file.csv URLのようにcurlコマンドによるファイルアップロードと同等の処理とするために、ファイルをストリームとして送信する点です。

あとは、これをIM-LogicDesignerの拡張機能として取り込んで完了です。拡張モジュールの作成方法は、以下の手順で実行しintra-martのwarファイルに含めるように再ビルドを実行します。

おわりに

今回は、IM-LogicDesignerからS3 Presigned URLによるファイルアップロードする際に問題となった点の解消方法について説明を行いました。ただし、この問題はPresigned URL生成時にContent-Typeが指定されていないという点に起因した問題です。一般的にはPresigned URL生成時のロジックにて対処するのが通常だと思いますが、都合によってはその対処ができないケースに遭遇することもあるかもしれません。その際のご参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?