ファイル型フィールドを扱う
フィールドの型に ファイル を選ぶと、行にファイル(CSV・画像・PDF など)を添付できます。ファイル本体は Synqlet のストレージに保存され、行にはそのファイル情報が保持されます。
画面から扱う
Section titled “画面から扱う”- 行の作成 / 編集画面でファイルを選択してアップロードします。
- 行の詳細画面でプレビュー・ダウンロードができます。
- 行を削除すると、その行に添付されていたファイルも削除されます。
スクリプトから扱う
Section titled “スクリプトから扱う”synqlet:database/{テーブルのID} では、ファイル型フィールドの値に次の型を使います。
取得したファイル(FileOutput)
Section titled “取得したファイル(FileOutput)”{ name: string; // ファイル名 mimeType: string; // MIMEタイプ size: number; // バイト数 url: string; // ダウンロード用の署名付きURL(発行から1時間有効)}url はそのまま fetch すればファイルの内容を取得できます。
import * as documents from "synqlet:database/{テーブルのID}";
const row = await documents.get(documents.Id("doc-001"));const file = row.values.attachment;if (file) { const response = await fetch(file.url); const text = await response.text(); console.log(file.name, text.length);}新しいファイルを保存する(FileInput)
Section titled “新しいファイルを保存する(FileInput)”stream / mimeType / name を指定すると、ファイル本体をアップロードして行に添付します。
固定テキストサンプル
import * as table from "synqlet:database/{テーブルのID}";
await table.insertOne({ values: { title: "日次レポート", attachment: { stream: new Blob([ `id,name1,サンプル`, ]).stream(), mimeType: "text/csv", name: "report.csv", }, },});stream には ReadableStream<Uint8Array> を渡します。fetch のレスポンスボディをそのまま渡すこともできます。
const response = await fetch("https://example.com/data.csv");if (response.body) { await table.insertOne({ values: { title: "取り込みデータ", attachment: { stream: response.body, mimeType: "text/csv", name: "data.csv", }, }, });}ストリーム処理(大きなファイルを1行ずつ変換する)
ファイル全体をメモリに読み込まずに、ダウンロードしたストリームを変換してそのまま stream に渡せます。次は jsr:@std/csv で CSV を1行ずつ読み取り、列を加工しながら保存する例です。
import * as table from "synqlet:database/{テーブルのID}";import { CsvParseStream, CsvStringifyStream } from "jsr:@std/csv";
export default async function () { const source = await table.get(table.Id("{行のID}"));
const response = await fetch(source.values.attachment.url); if (!response.body) { throw new Error("ファイルの取得に失敗しました"); }
// ヘッダー行を列名として使い、1行ずつオブジェクトとして受け取る const rowStream = response.body .pipeThrough(new TextDecoderStream()) .pipeThrough(new CsvParseStream({ skipFirstRow: true }));
await table.insertOne({ values: { title: "取り込みデータ", attachment: { stream: ReadableStream.from( (async function* () { for await (const row of rowStream) { yield { name: row.name, per: Number.parseInt(row.score) / 100 }; } })(), ) .pipeThrough(new CsvStringifyStream({ columns: ["name", "per"] })) .pipeThrough(new TextEncoderStream()), mimeType: "text/csv", name: "data.csv", }, }, });
return {};}既にあるファイルをコピーする
Section titled “既にあるファイルをコピーする”取得済みのファイル(FileOutput)をそのまま渡すと、ファイル本体を送り直さずにサーバー側でコピー されます。大きなファイルでも通信量が増えません。
コピー元にできるのは次の2つです。
| コピー元 | 例 |
|---|---|
| 別のテーブル(または同じテーブル)の行のファイル | get() / list() で取得した値 |
| フロージョブの添付ファイル | フォームトリガーで受け取ったファイル(Parameter の値) |
import * as documents from "synqlet:database/{テーブルのID}";import * as archives from "synqlet:database/{別テーブルのID}";
export default async function (parameter) { // フォームでアップロードされたファイルをテーブルに保存する await documents.insertOne({ values: { title: "申請書", attachment: parameter.upload }, });
// 別テーブルの行のファイルをコピーする(名前だけ変更もできる) const row = await documents.get(documents.Id("doc-001")); const file = row.values.attachment; if (file) { await archives.insertOne({ values: { attachment: { ...file, name: "アーカイブ.csv" } }, }); }
return {};}ノードの結果としてファイルを渡す
Section titled “ノードの結果としてファイルを渡す”ノードの型(Result)にファイル型の項目を定義しておくと、テーブルから取得したファイルを次のノードへ渡せます。この場合もファイル本体は送り直されず、フロージョブの添付ファイルとしてコピーされます。
const row = await documents.get(documents.Id("doc-001"));
return { attachment: row.values.attachment };制限・注意点
Section titled “制限・注意点”- 行を削除するとファイルも削除されます。行の更新でファイルを差し替えると、参照されなくなった古いファイルは自動的に削除されます。
- ファイル型フィールドは、画面のフィルターでは絞り込めません。スクリプトや REST API からは
name/mimeType/size/idで絞り込めます。 - ファイル型フィールドでの並び替えはできません。
- MIMEタイプとファイルサイズは、アップロードされた実際のファイルの情報がサーバー側で記録されます。
- スクリプトからデータベースを操作する
- テーブルとフィールドを設計する
- データベースの REST API
- トリガーを設定する(フォームトリガーでのファイル受け取り)