BoxにNode.jsからファイルアップロードメモ


[Box](https://www.box.com/ja-jp)のAPIを使ってファイルアップロードを試してみます。

## シンプルなサンプル

https://github.com/box/box-node-sdk 

こちらのSDKを使って試してみましたが、割とシンプルに動きました。

ドキュメントを見つつasync/awaitに書き換えてます。

> https://github.com/box/box-node-sdk/blob/main/docs/files.md#upload-a-file

```js
'use strict';

const BoxSDK = require('box-node-sdk');
const fs = require('fs');

// Initialize the SDK with your app credentials
const sdk = new BoxSDK({
  clientID: 'xxxxxxxxxxx',
  clientSecret: 'xxxxxxxxxxxx'
});
const client = sdk.getBasicClient('xxxxxxxxxxxxxx');


const main = async () => {
    const fileName = `test.png`;
    const uploadBoxFolderId = 'xxxxxxxxxxxxxx';
    
    try {
        const stream = fs.createReadStream(`./${fileName}`);
        const file = await client.files.uploadFile(uploadBoxFolderId, fileName, stream)
        console.log(file);
    } catch (err) {
        console.log(err);
    }
}   

main();
```

## 分割アップロード（Chunked Upload）/ 大きいファイル

大きいファイルを扱う場合は分割アップロードをするのが良いらしいです。

> https://github.com/box/box-node-sdk/blob/main/docs/files.md#chunked-upload

`getChunkedUploader()`という関数があるので使ってみます。

```js
//省略

const main = async () => {
    const fileName = `my.pdf`;
    const uploadBoxFolderId = '160667378861';
    try {
        const data = fs.readFileSync(`./${fileName}`);
        const stream = fs.createReadStream(`./${fileName}`);
        client.files.getChunkedUploader(uploadBoxFolderId, data.length, fileName, stream)
        .then(uploader => uploader.start())
        .then(file => {
            console.log(file);
        });
    } catch (err) {
        console.log(err);
    }
}   

main();
```

うまくいきました。ちなみに、この時使ったpdfは66MBでした。

小さいファイルを上げようとすると

> ![スクリーンショット 2022-04-12 17.02.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/03baa38d-ac02-3ed0-4f6f-2a139b0734f8.png "スクリーンショット 2022-04-12 17.02.21.png")

> Unhandled rejection Error: Unexpected API Response [400 Bad Request | 39e1f076a25cfd2867df145166f395cc] file_size_too_small - File size 225156 less than minimum allowed for this API: 20000000

エラーを見る限りだとおそらく **20MB未満は分割アップロードでは使えない模様です。**

逆に20MB以上は分割アップロードをするのが良さそうですね。

## tipsなど

### フォルダーIDについて

- ブラウザで開いた時のURLの`/folder/xxxxxxxxxxx`のxxxxxxxxx部分
	- この場合は`160667378861`がフォルダーID

> ![](https://i.gyazo.com/5001b437681ef1f9792137ca71b5ebec.png)

- ルートディレクトリのIDが`0`で固定っぽい

参考: https://qiita.com/yama9112/items/e548083a38365d6ec951

### デフォルトで60分らしい、開発者トークン

デフォルトで60分らしい。
よく分からず試していて、急に動かなくなって焦りました。

> https://ja.developer.box.com/guides/authentication/tokens/developer-tokens/

### アクションスコープのチェック

試した環境だとデフォルトで書き込み権限にチェックが入ってなかったのでこちらを忘れずに設定しておく。

> ![スクリーンショット 2022-04-12 16.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/00ea3c09-7b60-c2a8-82ef-2256b89abb3f.png "スクリーンショット 2022-04-12 16.52.37.png")

### そのまま上書きは出来ない

Google Driveなどの仕様とは違うみたいで、同じファイル名でアップロードしようとすると怒られました。

> ![スクリーンショット 2022-04-12 17.10.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/2641ca72-50bd-8b9d-09b3-98ffc7c3f63f.png "スクリーンショット 2022-04-12 17.10.33.png")
> Unhandled rejection Error: Unexpected API Response [409 Conflict | 7zmyo4h1706s8fpi] item_name_in_use - Item with the same name already exists


## まとめ

慣れると比較的簡単に使えましたが、設定周りの癖がありますね。
慣れるとGoogle系APIより楽かもしれません。