blog
ブログ

Salesforce技術ブログ(VF開発で厄介な「apex:inputFile can not be used in conjunction with~」エラーを回避する!)

みなさん初めまして!いつもクールでドライな、ドライ市来です!

今回は、Visualforceページを作成していてよく聞く問題の対処法です。

はじめに

画面からCSVファイルを読み込んで、マスタデータを一括更新!!

複数のレコードに画像ファイルを紐づけ!!

等のVisualforceを作成中、↓の画面のようなエラー画面に出くわした方いらっしゃいませんか。

Salesforce_inputFileエラー画面
結構厄介ですよね。これ↓

apex:inputFile can not be used in conjunction with an action component, apex:commandButton or apex:commandLink that specifies a rerender or oncomplete attribute.

そこで、今回はJavascriptと<input type=”file”>と<apex:actionFunction>を使った回避方法を紹介します。

回避方法

回避方法をざっくりと説明すると
<apex:inputFile>ではなく<input type=”file”>を使い、Javascriptで読み込んだファイルをごにょごにょし、
<apex:actionFunction>でApexを呼び出してファイルの情報を渡してる感じです。

以下サンプルです。

Visualforce

<apex:page id="pgid" controller="Sample_InputFileCon" >
  <apex:form id="form_id">
    <apex:actionFunction name="passToController" action="{!readCsvFile}" oncomplete="onCompleteAction('{!isSuccess}');">
      <apex:param name="fname" value="" assignTo="{!filename}" />
      <apex:param name="body" value="" assignTo="{!body}"/>
    </apex:actionFunction>
    <apex:pageMessages id="msg_id"/>
    <apex:pageBlock id="pageBlock_id" >
      <apex:pageBlockSection >
        <input type="file" id="file_input" name="attFile" accept=".csv" /><br/>
        <apex:commandButton value="CSV読み込み" onclick="remoteLocationPost(); return false;"/>
      </apex:pageBlockSection>
    </apex:pageBlock>
    <script>
    var blobfile;
    function getAsText(readFile) {
    var reader = new FileReader();
      reader.readAsDataURL(readFile);
      reader.onload = attLoaded;
    }
    function attLoaded(evt) { 
      var fileString = evt.target.result;
      blobfile = fileString;
      var input = document.getElementById("file_input");
      var filename= input.value;
      passToController(filename,blobfile);
    }
    function remoteLocationPost(){
      var fbody= document.getElementById("file_input").files[0];
      if(typeof fbody === "undefined"){
        alert("CSVファイルが選択されていません。");
        return;
      }
      else{
        getAsText(fbody); 
      }
    }
    function onCompleteAction(ret){
      if(ret == 'true'){
        alert('CSV読み込み完了');
      }
      else{
        alert('CSV読み込み失敗');
      }
    }
    </script>
  </apex:form>
</apex:page>

Apex

public class Sample_InputFileCon {
    public String filename {get; set;}
    public String body {get; set;}
    public Boolean isSuccess {get; set;}

    public Sample_InputFileCon(){
        filename = '';
        body = '';
        isSuccess = false;
    }

    // CSV読み込み
    public void readCsvFile(){
        try{
            body = body.substringAfterLast(',');
            Blob csvFileBody = EncodingUtil.base64Decode(body);

            // ファイル解析処理
            // ~~~略~~~

            isSuccess = true;
        }
        catch(Exception e){
            isSuccess = false;
        }
    }
}

実装例(※GIFとなっています。画像をClick)

InputFile_Sample01

この方法を使用することで、エラーを回避し、処理を実現することができます!

contact

ご相談・ご質問等ございましたら、お気軽にお問い合わせください。

翻訳