DatabricksのFileStore

[FileStore \| Databricks on AWS](https://docs.databricks.com/data/filestore.html#embed-static-images-in-notebooks) [2021/3/17時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

FileStoreは[Databricksファイルシステム\(DBFS\)](https://qiita.com/taka_yayoi/items/897264c486e179d72247)の特殊なフォルダーであり、保存したファイルにお使いのWebブラウザーからアクセスすることができます。以下のような用途でFileStoreを活用することができます。

- `displayHTML`関数を呼び出す際に、HTMLやJavaScriptからアクセスできる画像やライブラリを保存する。
- ローカルマシンにダウンロードしたい出力ファイルを保存する。
- Databricksで処理するために、CSVや他のデータファイルをローカルマシンからアップロードする。

特定の機能を使用する際、DatabricksはFileStore配下の以下のフォルダーにファイルを保存します。

- `/FileStore/jars` - アップロードした[ライブラリ](https://docs.databricks.com/libraries/workspace-libraries.html#uploading-libraries)が格納されます。このフォルダーのファイルを削除すると、ワークスペースでこれらのファイルを参照するライブラリは動作しなくなります。
- `/FileStore/tables` - [UI](https://qiita.com/taka_yayoi/items/4fa98b343a91b8eaa480#%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88)を用いてインポートしたファイルが格納されます。このフォルダーのファイルを削除すると、これらのファイルから作成したテーブルにはアクセスできなくなります。
- `/FileStore/plots` - ノートブックで`ggplot`や`matplotlib`プロットのようなPython、Rプロットオブジェクトに対して`display()`関数を呼び出した際に作成される画像が格納されます。このフォルダーのファイルを削除した場合、これらを参照するノートブックでこれらのプロットを再生成する必要があるかもしれません。詳細は[Matplotlib](https://docs.databricks.com/notebooks/visualizations/matplotlib.html)、[ggplot2](https://docs.databricks.com/notebooks/visualizations/ggplot2.html)を参照ください。 
- `/FileStore/import-stage` - [ノートブック](https://qiita.com/taka_yayoi/items/c306161906d6d34e8bd5#%E3%83%8E%E3%83%BC%E3%83%88%E3%83%96%E3%83%83%E3%82%AF%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88)や[Databricksアーカイブ](https://qiita.com/taka_yayoi/items/c306161906d6d34e8bd5#%E3%83%8E%E3%83%BC%E3%83%88%E3%83%96%E3%83%83%E3%82%AF%E3%81%AE%E9%85%8D%E5%B8%83)ファイルをインポートする際に生成される一時ファイルが格納されます。これらの一時ファイルはノートブックのインポートが完了すると削除されます。

# FileStoreにファイルを保存する

FileStoreにファイルを保存するには、DBFSの`/FileStore`ディレクトリに保存します。

```py:Python
dbutils.fs.put("/FileStore/my-stuff/my-file.txt", "Contents of my file")
```

以下では、`<databricks-instance>`はお使いのDatabricksデプロイメントの[ワークスペースURL](https://qiita.com/taka_yayoi/items/7127cabac70dd994fcba#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8Durlid)で置き換えてください。

`/FileStore`に格納されたファイルは、お使いのブラウザで`https://<databricks-instance>/files/`からアクセスすることができます。例えば、`/FileStore/my-stuff/my-file.txt`に格納したファイルは`https://<databricks-instance>/files/my-stuff/my-file.txt`でアクセスすることができます。

しかし、デプロイメントURLに`?o=`が含まれている場合、例えば、`https://<databricks-instance>/?o=6280049833385130`という場合は、`https://<databricks-instance>/files/my-stuff/my-file.txt`を`https://<databricks-instance>/files/my-stuff/my-file.txt?o=######`で置き換えてください。`o=`の後の数字は、お使いのURLに含まれているものと同じものとなります。

> **注意**
`/FileStore`に直接ファイルを保存するために、DBFSのファイルアップロードインタフェースを使うこともできます。[ファイルアップロードインタフェース](https://qiita.com/taka_yayoi/items/897264c486e179d72247#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9)を参照ください。

# ノートブックに静的な画像を埋め込む

ノートブックに静的な画像を埋め込むために`/files`の場所を使用することができます。

```py:Python
displayHTML("<img src ='files/image.jpg/'>")
```

あるいは、マークダウンの画像インポートシンタックスを使用できます。

```
%md
![my_test_image](files/image.jpg)
```

DBFSのDatabricks [REST API](https://docs.databricks.com/dev-tools/api/index.html)とPython HTTPライブラリの[requests](https://requests.readthedocs.io/en/master/)を用いて、静的な画像をアップロードすることができます。以下の例では、

- `<databricks-instance>`はお使いのDatabricksデプロイメントの[ワークスペースURL](https://docs.databricks.com/workspace/workspace-details.html#workspace-url)で置き換えてください。
- `<token>`はご自身の[パーソナルアクセストークン](https://docs.databricks.com/dev-tools/api/latest/authentication.html#token-management)を指定してください。
- `FileStore`配下の`<image-dir>`には画像ファイルをアップロードしたい場所を指定してください。

```py:Python
import requests
import json
import os

TOKEN = '<token>'
headers = {'Authorization': 'Bearer %s' % TOKEN}
url = "https://<databricks-instance>/api/2.0"
dbfs_dir = "dbfs:/FileStore/<image-dir>/"

def perform_query(path, headers, data={}):
  session = requests.Session()
  resp = session.request('POST', url + path, data=json.dumps(data), verify=True, headers=headers)
  return resp.json()

def mkdirs(path, headers):
  _data = {}
  _data['path'] = path
  return perform_query('/dbfs/mkdirs', headers=headers, data=_data)

def create(path, overwrite, headers):
  _data = {}
  _data['path'] = path
  _data['overwrite'] = overwrite
  return perform_query('/dbfs/create', headers=headers, data=_data)

def add_block(handle, data, headers):
  _data = {}
  _data['handle'] = handle
  _data['data'] = data
  return perform_query('/dbfs/add-block', headers=headers, data=_data)

def close(handle, headers):
  _data = {}
  _data['handle'] = handle
  return perform_query('/dbfs/close', headers=headers, data=_data)

def put_file(src_path, dbfs_path, overwrite, headers):
  handle = create(dbfs_path, overwrite, headers=headers)['handle']
  print("Putting file: " + dbfs_path)
  with open(src_path, 'rb') as local_file:
    while True:
      contents = local_file.read(2**20)
      if len(contents) == 0:
        break
      add_block(handle, b64encode(contents).decode(), headers=headers)
    close(handle, headers=headers)

mkdirs(path=dbfs_dir, headers=headers)
files = [f for f in os.listdir('.') if os.path.isfile(f)]
for f in files:
  if ".png" in f:
    target_path = dbfs_dir + f
    resp = put_file(src_path=f, dbfs_path=target_path, overwrite=True, headers=headers)
    if resp == None:
      print("Success")
    else:
      print(resp)
```

## 静的な画像のスケールを変更する

DBFSに保存した画像のサイズを変更するには、画像を`/FileStore`にコピーし、`displayHTML`の画像パラメーターを用いてリサイズします。

```py:Python
dbutils.fs.cp('dbfs:/user/experimental/MyImage-1.png','dbfs:/FileStore/images/')
displayHTML('''<img src="files/images/MyImage-1.png" style="width:600px;height:600px;">''')
```

# Javascriptライブラリを使う

このノートブックでは、JavaScriptライブラリを使用するためにどのようにFileStoreを使用するのかを説明します。

## FileStoreデモノートブック

https://docs.databricks.com/_static/notebooks/filestore.html

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)