ローカルCSVにあるPDFファイル含むすべてのデータをkintoneアプリにアップロードしたい

何を実現したいのかを書きましょう

ローカルにあるCSVファイルに添付ファイル(pdf/docx)があり、添付ファイル以外うまくアップロードできましたが添付ファイルができません、添付ファイルをアップロードできるよい方法があればご教授をよろしくお願い致します

以下のコードは以下のエラーでできませんでした。{“code”:“CB_OA01”,“id”:“zm13JV508UTNMWO8pWPD”,“message”:“Cannot access protected resource.”}

#!/bin/bash
set -e

appId=1
apiToken='xxxxxxxxxx'
domain='https://example.cybozu.com/'
csvFilePath='./project1.csv'

# CSVファイルの読み取りとレコードの処理
while IFS=$'\t' read -r PROJECT_ID ATTACHED_FILE; do
  echo "Processing PROJECT_ID: $PROJECT_ID, ATTACHED_FILE: $ATTACHED_FILE"

  # プロジェクトIDが空の場合はスキップ
  if [ -z "$PROJECT_ID" ]; then
    echo "Skipping due to empty PROJECT_ID."
    continue
  fi

  # ファイルキーの取得
  echo "Uploading file: $ATTACHED_FILE"
  fileKey=$(curl -X POST "${domain}/k/v1/file.json" \
    -H "Authorization: Bearer ${apiToken}" \
    -F "file=@${ATTACHED_FILE}" | jq -r '.fileKey')

  echo "File uploaded successfully. File Key: $fileKey"

  # レコードの更新
  curl -X PUT "${domain}/k/v1/record.json" \
    -H "Authorization: Bearer ${apiToken}" \
    -H "Content-Type: application/json; charset=Shift-JIS" \
    -d '{
      "app": '$appId',
      "id": "'$PROJECT_ID'",
      "record": {
        "ATTACHED_FILE": [
          {
            "fileKey": "'$fileKey'"
          }
        ]
      }
    }'

  echo "Attachment uploaded for PROJECT_ID: $PROJECT_ID"
done < <(tail -n +2 "$csvFilePath")

@PL.2023 さん

こんにちは、一点気になったので回答させていただきました。
まず、エラーですが直訳すると「保護されたリソースにアクセスできません」だと思いますが、
そちらを踏まえて、ファイルのアップロード及びfilekeyを取得される部分にヘッダー情報でのapiTokenの指定方法が違うと思いました。
恐らくですが、下記のような形になるかと思われます。

  fileKey=$(curl -X POST "${domain}/k/v1/file.json" \
    -H "X-Cybozu-API-Token: ${apiToken}" \
    -F "file=@${ATTACHED_FILE}" | jq -r ".fileKey")

@y_minamitani9534
こんにちは、ご連絡ありがとうございます。
はい、おっしゃる通りですがご指摘コードで試してみましたが全く同じエラーがでました。

ちなみにですが、filekeyは取得できているのでしょうか?
また、jqコマンドを抜かれた状態でも試されましたでしょうか?

1 Like

@y_minamitani9534
返信遅くなり申し訳ありません。
filekeyは正しく取得でいています。
jqコマンドを抜かれた状態では試していませんでした。

filekeyが正しい値で取得できているのであれば、恐らくjqコマンドは関係ないかなと思いますね…
眺めていて一点気になったところがございました。
ここですが、

{"record": {
        "ATTACHED_FILE": [
          {
            "fileKey": "'$fileKey'"
          }
        ]
    }
}

恐らく、こうじゃないかなと思われます↓

{"record": {
        "ATTACHED_FILE": {
            "value":[
              {
                "fileKey": "'$fileKey'",
              },
            ]
          }
      }
  }

エラーメッセージから考えたら少し違うような気もしますが、一度試していただければと…

@y_minamitani9534
ありがとうございます。
同じエラー出ました。

参考情報です。
エラーコード CB_OA01 で検索すると以下のページが見つかりました。
Google Apps ScriptでKintoneのユーザ一覧を取得する【GAS】 :palm_tree: officeの杜 :coconut:

403エラー「CB_OA01 : cannot access protected resource」で全てエラーになります

認証がらみの何かでしょうかね?

ただ、添付ファイル以外はアップロードできているという内容なので矛盾している気もしますが、質問文で貼り付けたヘッダーの内容では動かない内容だったのでなんとも言えない印象です。

1 Like

こんにちは。

cybozu office 10(オンプレ版)が販売停止するに伴い、弊社ではgaroon×kintoneに移行する事になりました。
その時にカスタムアプリ内の添付ファイルを一括してアップロードする膨大な作業にブチ当たり、先人の知恵を拝借しながらスクリプトを調整し移行に成功しましたので、共有させていただきますね。(ほとんどベースのままですが…)
過去コミュニティの以下リンクにあったものをベースに、エラーの出た箇所だけを手直ししてトライアンドエラーで漸く一括アップロードを成功させたという感じですので、正直私もスクリプトの理解度は2割程度ですが、ご参考になれば幸いです。

もとにしたスクリプトは、実際は @PL.2023 さんの行いたい事がドンピシャで出来そうな感じだったんですが、私の技術力では限界がありましたので「第1段階でこのスクリプトを用いて添付ファイルのみアップロードし、第2段階として文字ベースの情報を標準の取込機能を使ってレコード更新」という方法を取りました。

前提

  • vscode利用
  • node.js利用

参考リンク

※もともと素晴らしいコードが貼り付けてあったんですが、コミュニティの移行に伴いスクリプト部分が消えてしまっているようです…

処理したスクリプト


(async () => {
    const util = require('util');
    const fs = require('fs');
    const iconv = require('./node_modules/iconv-lite');
    const {KintoneRestAPIClient} = require('./node_modules/@kintone/rest-api-client');
    const csvParse = require('./node_modules/csv-parse/dist/cjs/sync.cjs');

    const readFile = util.promisify(fs.readFile);

    const client = new KintoneRestAPIClient({
        baseUrl: 'https://<yourDomain>.cybozu.com',
        auth: { apiToken:'TOKEN'},
    });

    const app = 121; //アプリID
    const fileName = '添付ファイルリスト.csv'; //CSVファイルのパス
    const reverse = true; //データをCSVの逆順に登録するか否か

    const formFields = await client.app.getFormFields({ app });
    const datas = csvParse.parse(
        iconv.decode(
            Buffer.from(await readFile(fileName),'binary'),
            'Shift_JIS'
            ), {
            delimiter: ',',
            rowDelimiter: 'auto',
            quote: '"'
    });
    const headers = datas[0].reduce((headers, header, index) => {
        const property = Object.values(formFields.properties).find(property => property.label === header);
        if (typeof property !== 'undefined'){
            if ([
                'RECORD_NUMBER',
                '__ID__',
                '__REVISION__',
                'CREATOR',
                'MODIFIER',
                'CREATED_TIME',
                'UPDATED_TIME',
                'CATEGORY',
                'STATUS',
                'STATUS_ASSIGNEE'
            ].includes(property.type)){
                return headers;
            }
            headers.push({
                index,
                type: property.type,
                code: property.code
            });
            return headers;
        }
    }, []);
    const files = await Promise.all(
        datas.slice(1).map(
            data => headers.filter(header => header.type === 'FILE').map(
                header => data[header.index].split(',')
            )
        ).flat(2).map(path => client.file.uploadFile({
                file: {
                    path
                }
        }))
    );
    let fileIndex = 0;
    const records = datas.slice(1).map(data => headers.reduce((record, header) => {
        if (header.type === 'FILE') {
            record[header.code] = {
                value: data[header.index].split(',').map(filePath => {
                    return files[fileIndex++];
                })
            };
        } else {
            record[header.code] = { value: data[header.index] };
        }
        return record;
    }, {}));
    if (reverse)
        records.reverse();
    await client.record.addAllRecords({ app, records });
    
    console.log('レコードを追加しました.');
})();

1 Like

@aaa
こんにちは、
情報共有ありがとうございました。
参考にさせて頂きます。
認証がらみのところですがあまり添付ファイルアップロードするさいには特に必要なさそうでした。とりあえず認証はスキップしました。

1 Like

@t.nori
こんにちは。
情報共有ありがとうございました。参考にさせて頂きます。
共有させて頂いたコードはnode.jsですがkintoneのjavascript/cssカスタマイズには使用できないと思いますがkintoneのカスタマイズにnode.jsをどのように活用しますでしょうか?

すみません。意味がわかりませんでした。

最後に試されたコードを提示してもらってもいいですか?
ちなみにfilekeyが正常取得とはどうやって確認しましたか?
ちなみに認証できなければファイルのアップロードはできませんし、仮にアップロードできているのであれば対象の添付ファイルフィールドに対して取得したfilekeyを使って更新すれば添付ファイルフィールドにセットされるはずです。

私が提示したスクリプトは主に「初期データを外部から一括投入」といったシチュエーションで利用されるものかなと思います。
またnode.jsについては、本スクリプトをサポートしてくれるjsファイル群かなといった認識です。
@PL.2023 さんが仰っているようなkintoneアプリ上のjavascript/cssカスタマイズとしての利用とは違ったものになります。

以下、私が実行した手順を簡単に記載させていただきますね。

ちなみに私の環境はwindows10proになります。

  1. vscodeを起動する
  2. node.jsパッケージと呼ばれるjsパッケージをダウンロードする
  3. node.jsパッケージフォルダがある場所に「main.js」というテキストファイルを作成し上のスクリプトを保存する
  4. vscodeのカレントディレクトリ?を「main.js」の場所に変更する
  5. vscodeのターミナル上で「node main.js」と入力し実行

ありがとうございます。理解しました。

1 Like

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。