SalesforceにファイルをUploadしたいとき、どうするか?
Salesforceに静的な資源(画像なりPDFなりCSSなり)を置いて、LWC等でその資源を利用するというシーンはよくあると思います。
そういった時に、どんなファイルストレージを使うべきでしょうか?
一般的には静的リソースとSalesforce Filesが有名だと思いますが、マイナーながら実は ContentAsset という第三の選択肢が存在しており、これがなかなか便利なのでこの記事で紹介します。
ContentAssetとは、ズバリSalesforce Filesをメタデータとして管理できるようにしたものです。強みと弱みも、基本はSalesforce Filesのものを引き継ぎます。しかし、大きな違いとして、ファイルをメタデータとしてデプロイできるということが挙げられます。
これらの違いを、まずは表にまとめてみます。
方式 | 強み | 弱み | 主な用途 |
---|---|---|---|
静的リソース |
|
|
|
Salesforce Files (ContentVersion & ContentDocument) |
|
|
|
ContentAsset |
|
|
|
キャッシュの有無を気にしなければ、静的リソースとSalesforceの良いとこどりですね!
※なお、かつては「ドキュメント」や「Attachment」にファイルを格納することもありましたが、現在ではファイルにとって代わられているため上記の表では割愛します。
#どんな時に便利?
ユースケースの例:
- LWCに貼ったリンクをクリックするとマニュアル(数十MBのPDF)を表示したい
- LWCでボタンをクリックすると動画を再生したい
…余談ですが、私は郵便番号入力時の住所自動入力に使えるコンポーネントを作ろうとした際に使いました。
仕組みとしては、曰くつきの有名な郵便番号のzipをContentAssetに置いて、LWC初期化時にそれをロードしてJSZipを使ってJavaScriptで解凍し、郵便番号がテキスト欄に入力されたらzipの中にあるCSVの行を正規表現でひっかけて一致する住所を取ってくるというものです。毎月の郵便番号データ最新化をzip置き換えだけで済ませたかったのとApexガバナ制限を回避したかったのとで、zipをクライアント側にダウンロードしてJavaScriptで解凍して走査するという変わった方式を採りました。なかなかキビキビ動いてくれて、実用に耐えうるものになりました。ただ、その後、lightning-input-addressに郵便番号のルックアップ機能があることに気づいたのでこのコンポーネントは捨てることにしました。(要は車輪の再発明でした。)
どうやって使うの?
1. ファイルのUpload
Uploadには以下の2種類があります。
- 方式①:ApexでInsertする
Blob yourFile = xxxxx; //ここでファイルのBlobを生成
ContentVersion cvForKenAll = new ContentVersion(
VersionData = yourFile,
Title = 'Your file',
PathOnClient = 'yourFile.zip',
IsAssetEnabled = true //ここが重要!IsAssetEnabledをtrueにしてContentVersionをInsertすることでContentAsset扱いでUploadされる。
);
- 方式②:メタデータをデプロイする
force-app/main/default/contentassets
- yourfile.asset ←ここにバイナリを格納
- yourfile.asset-meta.xml ←ここに定義(下記ファイル)を格納
<?xml version="1.0" encoding="UTF-8"?>
<ContentAsset xmlns="http://soap.sforce.com/2006/04/metadata">
<isVisibleByExternalUsers>true</isVisibleByExternalUsers>
<language>ja</language>
<masterLabel>yourfile</masterLabel>
<versions>
<version>
<number>1</number>
<pathOnClient>yourfile.zip</pathOnClient>
</version>
</versions>
</ContentAsset>
2. ファイルの利用
LWCで以下のように定義する:
import YOURFILE_URL from '@salesforce/contentAssetUrl/yourfile';
export default class AssetFileExample extends LightningElement {
yourFileURL = YOURFILE_URL;
}
これで「yourFileURL」変数にファイルのURLが格納されるので、あとはfetchするなりHTMLの各種タグのsrcに使うなり、お好きにどうぞ!
FAQ
####Q: 外部ユーザにも表示させられる?
A: ContentAssetオブジェクトの「isVisibleByExternalUsers」をtrueにセットすれば表示させられる。
####Q: 削除するにはどうすればよいの?
A: ContentAssetが紐づくContentDocumentを削除すれば、ContentDocumentのみならず、紐づくContentAsset / ContentVersionもろとも消えてくれる。ContentAssetが紐づくContentDocumentのIdは、[SELECT ContentDocumentId FROM ContentAsset WHERE DeveloperName='xxxx']で取得可能。
####Q: 既にLWCで参照を張っているContentAssetを削除しようとするとどうなる?
A: エラーになって削除できないようになっている。
####Q: ファイルのバージョンを上げるには?
A: ContentVersionと同じ方法でOK。つまり、新規ContentVersionを、[ContentDocumentId = {ContentAssetが紐づくContentDocumentのId}]を指定しつつInsertすればよい。