2016.08.01
Visualforce開発で厄介な「apex:inputFile can not be used in conjunction with~」エラーを回避する!
こんにちは!
今回は、Visualforceページを作成していてよく聞く問題の対処法です。
はじめに
画面からCSVファイルを読み込んで、マスタデータを一括更新!! や 複数のレコードに画像ファイルを紐づけ!! 等のVisualforceを作成中、↓の画面のようなエラー画面に出くわした方いらっしゃいませんか。 結構厄介ですよね。これ↓
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)
この方法を使用することで、エラーを回避し、処理を実現することができます!