end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

javascript+iframeによるajax風の画面遷移なしファイルアップロード

html5のFileReaderでドラッグ&ドロップなファイルのアップロード - end0tknrのkipple - web写経開発
以前、html5のFileReaderを使ったファイルアップロードのエントリを書いていますが、iframeを使ってajax風の画面遷移なしファイルアップロードを実現できるようなので、書いてみた。
Ajax的に画像などのファイルをアップロードする方法 ::ハブろぐ

で、触ってみたが、案外、いい感じ。

HTML

<nmw-args args="$pg,$view">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sing XXXXX</title>
<link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/default_2.css">
<script type="text/javascript" src="js/jquery.js"></script>
</head>
<body>
<nmw-include template="Common/Head.html" args="$pg,$view">

<div class="container-fluid">
  <h3>XXXXX</h3>
  <div id="sys_alert" class="alert" style="display:none;"></div>
  発注データをダウンロードし、以下のフォームからアップロードして下さい

  <form method="POST" id="file_form" enctype="multipart/form-data"
	target="dummy_elm">
    <input type="hidden" name="ac" value="chk_pre_juchuu_file">

    <table class="table table-bordered table-condensed">
      <tbody>
	<tr>
	  <th>見出ファイル</th>
	  <td>
	    <input type="file" id="midashi_file" name="midashi_file" size="20">
	  </td>
	  <th>明細ファイル</th>
	  <td>
	    <input type="file" id="meisai_file" name="meisai_file" size="20">
	  </td>
	  <td>
	    <input type="button" class="btn btn-primary" value="CSV内容確認"
		   onClick="pre_j.chk_pre_juchuu_file()">
	  </td>
	</tr>
      </tbody>
    </table>
  </form>
  <iframe src="" id="dummy_elm" name="dummy_elm" style="display:none;"></iframe>

  <input type="button" class="btn btn-primary"
	 value="以下の内容で、ハイム新着受注へ登録実行">

  <form method="POST" id="common_form">
    <div id="checked_juchuu">
    </div>
  </form> <!--#common_form-->
</div><!--.container-fluid-->


<div style="display:none"> <!--jquery template-->w
  <script id="tmpl_midashi_tbl" type="text/x-jquery-tmpl">
    <table class="table table-bordered table-condensed">
      <thead>
	<tr>
	  <th>発注NO</th>
	  <th>邸名</th>
	  <th>邸コード</th>
	  <th>納入日<br>納入先(希望)</th>
	  <th>発注日<br>(指定/実行)</th>
	  <th>担当<br>(受注/発注)</th>
	  <th>備考<br>メモ</th>
	</tr>
      </thead>
      <tbody>
      </tbody>
    </table>
  </script><!--#tmpl_midashi_tbl-->

  <script id="tmpl_midashi_tr" type="text/x-jquery-tmpl">
    <tr>
      <td>${official_id_org}</td>
      <td>${tei_name_kana}<br>${tei_name}</td>
      <td>${xxxx_teicode}</td>
      <td>${delivery_date}<br>${delivery_to}</td>
      <td>${hachuu_date}<br>${admit_hachuu_time}</td>
      <td>${admit_juchuu_user}<br>${admit_hachuu_user}</td>
      <td>${note}<br>${memo}</td>
    </tr>
  </script><!--#tmpl_midashi_tr-->

  <script id="tmpl_anken_tbl" type="text/x-jquery-tmpl">
    <table class="table table-bordered table-condensed">
      <thead>
	<tr>
	  <th>インポート先<br>案件</th>
	  <th>邸名</th>
	  <th>邸コード<br>商品タイプ</th>
	  <th>住所<br>(建築先/現住所)</th>
	  <th>据付予定<br>引渡予定</th>
	  <th>工事部署/担当<br>展示場/担当</th>
	  <th>更新情報</th>
	</tr>
      </thead>
      <tbody>
      </tbody>
    </table>
  </script><!--tmpl_anken_tbl-->

  <script id="tmpl_anken_tr_exist" type="text/x-jquery-tmpl">
    <tr>
      <td>
	<label><input type="radio" value="new">既存案件</label>
      </td>
      <td>${tei_name_kana}<br>${tei_name}</td>
      <td>${xxxx_teicode}<br>${xxxx_shouhin_type}</td>
      <td>${build_address}<br>${now_address}</td>
      <td>${xxxx_suetsuke_date}<br>${hikiwatashi_date}</td>
      <td>${kouji_busho} ${kouji_busho_tantou}<br>
	${xxxx_tenjijou} ${xxxx_tenjijou_tantou}</td>
      <td>${update_time}<br>${update_user}</td>
    </tr>
  </script><!--#tmpl_anken_tr_exist-->

  <script id="tmpl_anken_tr_new" type="text/x-jquery-tmpl">
    <tr>
      <td>
	<label><input type="radio" value="new">新規作成</label>
      </td>
      <td><input type="text" style="width:160px;"></td>
      <td colspan="5"></td>
    </tr>
  </script><!--#tmpl_midashi_tr-->

</div><!--jquery template-->

<script type="text/javascript" src="js/common.js"></script>
<script type="text/javascript" src="js/jquery.tmpl.js"></script>
<script type="text/javascript" src="js/PreJuchuu.js"></script>
<script>
  $(document).ready(function(){
  });
</script>
</body>
</html>

javascript

(function() {
    var PreJuchuu = function() {};
    PreJuchuu.prototype = {
        chk_pre_juchuu_file:function(){
            if($('#midashi_file').val() == undefined ||
               $('#meisai_file').val() == undefined){
                toast_alert('見出と明細両方のCSVファイルを指定して下さい');
                return;
            }
            
            //SUMIT完了後の処理
            var this_obj = this;
            $('#file_form').submit(function(){
                var dummy_elm = $('#dummy_elm'); //非表示iframe
                dummy_elm
                    .unbind()
                    .bind('load', function(){
                        //iframeの内容取得
                        var json_txt = dummy_elm.contents().find('pre').html();
                        this_obj.disp_checked_pre_juchuu(json_txt);
                    });
            });

            $('#file_form').submit(); //SUBMIT
            return;
        },

        disp_checked_pre_juchuu:function(json_txt){
            var res = eval('('+json_txt+')'); //json to obj
            if (res.result != 'success'){
                toast_alert(res.msg);
                return;
            }

            $("#checked_juchuu").empty();
            
            var midashi_tbl =
                $("#tmpl_midashi_tbl").tmpl().appendTo("#checked_juchuu");
            for(var i=0; i<res.midashis.length; i++){
                var midashi = res.midashis[i];
                $("#tmpl_midashi_tr").tmpl(midashi ).appendTo(midashi_tbl);
            }

            var anken_tbl =
                $("#tmpl_anken_tbl").tmpl().appendTo("#checked_juchuu");
            $("#tmpl_anken_tr_new").tmpl().appendTo(anken_tbl);
        }

    };
    window.pre_j = new PreJuchuu();
})();

server side View Class(perl)

package XXXX::View::Juchuu::PreJuchuu;
use strict;
use utf8;
use base qw(XXXX::View);
use Encode;
use Text::CSV_XS;
use Data::Dumper;

my @PRE_MIDASHI_COLS =
    qw/official_id_org tei_name tei_name_kana
       hachuu_date admit_hachuu_time admit_hachuu_user admit_juchuu_user
       delivery_houhou delivery_date delivery_date_note delivery_to
       note memo teicode bukken_busho/;
my @PRE_MEISAI_COLS =
    qw/official_id_org page_id row_id
       room_name maker maker_id shouhin_code hinmei hinmei_code
       hinban color size juchuu_quantity unit
       juchuu_tanka hachuu_tanka kakeritsu juchuu_price hachuu_price
       note memo
       curtain_size_name curtain_size_rail curtain_cloth curtain_kan/;


sub new {
    my ($class, $dbh, $user) = @_;
    my $self = {dbh=>$dbh, user=>$user};
    $self = bless $self, $class;
    return $self;
}

sub load_pre_midashi {
    my ($self, $q) = @_;

    my $ret = {};
    #upload時に /usr/tmp/にCGItemp63817のような形式で
    #一時uploadされ、処理が完了したら、CGI.pmが消すみたい
    my $temp_fh = $q->upload('midashi_file');
    return undef unless $temp_fh;
    my $file_path = $q->tmpFileName($temp_fh);
    my $csv = Text::CSV_XS->new ({binary =>1});

    open(my $fh,"<:encoding(cp932)",$file_path) or
	die "can't open pre_juchuu_midashi ($file_path)";
    my $i = 0;
    my @ret;
    while (my $row = $csv->getline($fh)) {
	next if $i++ == 0; #先頭行は見出なので、読飛し
	my $j=0;
	my $midashi = {};
	for my $atri_key ( @PRE_MIDASHI_COLS ){
	    $midashi->{$atri_key} = $self->trim($row->[$j++]);
	}
	push(@ret,$midashi);
    }
    close($fh) or die "can't close pre_juchuu_midashi ($file_path)";

    return \@ret;
}


sub load_pre_meisai {
    my ($self, $q) = @_;

    my $ret = {};
    #upload時に /usr/tmp/にCGItemp63817のような形式で
    #一時uploadされ、処理が完了したら、CGI.pmが消すみたい
    my $temp_fh = $q->upload('meisai_file');
    return undef unless $temp_fh;
    my $file_path = $q->tmpFileName($temp_fh); #ファイル名は $temp_fh にあり
    my $csv = Text::CSV_XS->new ({binary =>1});

    open(my $fh,"<:encoding(cp932)",$file_path) or
	die "can't open pre_juchuu_midashi ($file_path)";
    my $i = 0;
    my $ret = {};
    while (my $row = $csv->getline($fh)) {
	next if $i++ == 0; #先頭行は見出なので、読飛し

	if ($row->[0] and not defined($ret->{$row->[0]}) ){
	    $ret->{$row->[0]} = [];
	}
	my $j=0;
	my $meisai = {};
	for my $atri_key ( @PRE_MEISAI_COLS ){
	    $meisai->{$atri_key} = $self->trim($row->[$j++]);
	}
	push(@{$ret->{$row->[0]}}, \%$meisai);
    }
    close($fh) or die "can't close pre_juchuu_midashi ($file_path)";

    return $ret;
}


sub validate_pre_juchuu {
    my ($self) = @_;

    for my $midashi ( @{$ret->{midashis}} ){
	
    }
}

sub validate_midashi_official_id_org {
    my ($self,$pre_midashi) = @_;
    unless($pre_midashi){}
}

1;
__END__