3
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Salesforce ファイルアップロード使用事例

Last updated at Posted at 2020-07-25

Page側にファイルアップロードして、Salesforceオブジェクトに登録する実装例。

  • Visualforce側Pageの実装(関連部分の実装のみ表現)
Sample.v
<div class="file_drop_area">
    <div class="file_drop">
        <input type="file" class="file_drop" id="upload" accept="image/*, application/pdf" data-action-name="uploadFileAction" data-drop-area-class="file_drop_area" />
    </div>
    <apex:actionFunction action="{!pageUploadFile}" name="uploadFileAction" oncomplete="completeMsg();" rerender="refreshArea">
        <apex:param name="fileBody" value="" assignTo="{!fileBody}"/>
        <apex:param name="fname" value="" assignTo="{!fileName}" />
        <apex:param name="fileClass" value="" assignTo="{!fileClass}"/>
        <apex:param name="fileSize" value="" assignTo="{!fileSize}" />
    </apex:actionFunction>
</div>

  • JSの実装
Sample.js
$(function(){
  // ファイルドロップ時の設定
  $(document).on('dragenter', ".file_drop", function (e) {
      e.stopPropagation();
      e.preventDefault();
  });
  $(document).on('dragover', ".file_drop", function (e) {
      e.stopPropagation();
      e.preventDefault();
      e.originalEvent.dataTransfer.dropEffect = 'copy'; 
  });
  $(document).on('drop', ".file_drop", function (e) {
    e.stopPropagation();
    e.preventDefault();
    uploadFile(e.originalEvent.dataTransfer.files.item(0), $(this).data("action-name"), $(this).data("drop-area-class"));
  });

  // ファイル選択ダイアログの設定
  $(document).on('change', ".upload_file", function () {
    uploadFile($(this).prop('files')[0], $(this).data("action-name"), $(this).data("drop-area-class"));
    // ファイル選択状態を解除
    $(this).val("");
  });
});

/**
 * ファイルアップロード処理を行う大本。
 * ファイルアップロード時はこちらをまず呼び出す。
 * file:アップロードするファイル
 * actionName: アップロード時に実行する関数。apex:actionFunctionにて指定。
 * className: ファイルアップロードエリア(ファイルをドラッグするエリア)のクラス名。
 */
function uploadFile(file, actionName, className) {
  if (!validateUploadFile(file, className)) { // validateUploadFileの処理内容はここで割愛
    // バリデーションエラー時の処理
    return;
  }
  // 画像ファイルとPDFは処理が異なる
  if (file.type != "application/pdf") {
    uploadImageFile(actionName, file, className, file.type, file.size);
  } else {
    // 画像を読み込み
    var reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = event => {
      submitFile(actionName, event.target.result, file.name, className, file.type, file.size);
    };
  }
}

/**
 * 画像ファイル用アップロード処理。
 * 画像ファイルはアップロード時にファイルサイズを80%に落とす。
 * actionName: アップロード時に実行する関数。apex:actionFunctionにて指定。
 * file:アップロードするファイル
 * className: ファイルアップロードエリア(ファイルをドラッグするエリア)のクラス名。
 */
function uploadImageFile(actionName, file, className) {
  var reader = new FileReader();

  reader.readAsDataURL(file);
  reader.onload = event => {
    var img = new Image();
    img.src = event.target.result;
    img.onload = () => {
      
      var width = img.width;
      var height = img.height;
      
      var canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      var ctx = canvas.getContext('2d');
      
      // img.width and img.height will contain the original dimensions
      // 画像を再描する
      ctx.drawImage(img, 0, 0, width, height);
      submitFile(actionName, canvas.toDataURL(file.type, 0.8), file.name, className, file.type, file.size);
    },
    reader.onerror = error => console.log(error);
  };
}

/**
 * ファイルアップロード処理。
 * apex:actionFunctionで設定したcontrollerの処理を実行する関数を呼び出す。
 * actionName: アップロード時に実行する関数。apex:actionFunctionにて指定。
 * base64File:アップロードするファイルを変換したbase64文字列。
 * fileName: ユーザーがアップロードするファイルのファイル名。
 * className: ファイルアップロードエリア(ファイルをドラッグするエリア)のクラス名。
 */
function submitFile(actionName, base64File, fileName, className, fileType, fileSize) {
  //サーバ処理pageUploadFileを実行する
  Function('return this')()[actionName](base64File, fileName, fileType, fileSize);
  //ファイルドロップエリアの画像差し替え
  // 処理内容割愛(アップロードされた画像を画面にプレビュー)
  $("." + className).show();
}

  • Apex側の実装

    ガバナ制限を超えないように、ファイル内容を格納するプロパティをtransientで定義
Sample.cls
// ※ここが重要※ ガバナ制限を超えないように、ファイル内容を格納するプロパティをtransientで定義
public transient String fileBody {get; set;}// 添付ファイルデータ
public String fileName {get; set;}// 添付ファイル名	
public String fileClass {get; set;}// ファイルタイプ
public String fileSize {get; set;}// ファイルサイズ
/**
 * 画面からアップロード処理を行う.
 * @return PageReference
 */
public PageReference pageUploadFile(){
    try {
        // 添付書類を保存する(カスタムオブジェクトです。Contactとアップロード画像との紐付く関係を持っているためのオブジェクト)
        AttachedFile__c attFile = new AttachedFile__c(
                                          Test_Column__c = 'testColumn',
                                          File_Type__c = 'testType',
                                          Contact_Id__c = contact.Id);
        insert attachedFile;

        // 画像データ保存のため、取得したデータを処理する
        String fileData = fileBody.substring(fileBody.indexOf(',') + 1, fileBody.length());

        // コンテンツバージョンを保存する
        ContentVersion conVer = new ContentVersion();
        conVer.Title = fileName;// タイトル
        conVer.PathOnClient = fileName;// クライアントでのパス
        conVer.VersionData = EncodingUtil.Base64Decode(fileData);// バージョンデータ
        conVer.IsMajorVersion = true;// メジャーバージョン
        insert conVer;

        // ContentDocumentIdを取得する
        String recordId = conVerData.Id;
        String query = 'SELECT ContentDocumentId FROM ContentVersion  WHERE Id IN :recordId';
        ContentVersion conVerNew = Database.query(query);

        // コンテンツドキュメントリンクを保存する
        ContentDocumentLink conDocLink = new ContentDocumentLink();
        conDocLink.ContentDocumentId = conVerNew.ContentDocumentId;
        conDocLink.LinkedEntityId = attFileData.Id;
        conDocLink.ShareType = 'I'; // 必須 V、C、I(詳細の意味はAPI参照)
        conDocLink.Visibility = 'AllUsers'; // (他の設定値はAPI参照)
        insert conDocLink;

        // ContentDocumentオブジェクトの登録処理もありますが、その登録が自動で登録されるので、意識しなくて大丈夫です。
        // Contactデータを保存する(処理を省略)
        return null;
    } catch (Exception e) {
        // エラー処理
    }

3
8
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?