OZの部屋

なんでも日記です

CentoOS 5.5 ruby1.8 でRmagickインストール

2011-03-09 17:00:18 | ひまな話
ruby 1.8 が動いているとき
Rmagick のインストール
 ruby 1.8 ではRmagick1.x が対応 2.xは使えない

CentoOS 5.5のとき
■Rmagick
ImageMagick のインストール

yum install libjpeg-devel
yum install libpng-devel
yum install ImageMagick
yum install ImageMagick-devel

export LDFLAGS="-L/usr/lib"
export CPPFLAGS="-I/usr/include"
RMagick 2はだめ ruby 1.8では使えない
wget http://rubyforge.org/frs/download.php/47972/RMagick-1.15.17.tar.gz
tar xfz RMagick-1.15.17.tar.gz
cd RMagick-1.15.17
./configure --disable-htmldoc
make
make install
実行時にエラーがでる
/usr/local/lib/ruby/site_ruby/1.8/i686-linux/RMagick.so: /usr/local/lib/ruby/site_ruby/1.8/i686-linux/RMagick.so: cannot restore segment prot after reloc: Permission denied - /usr/local/lib/ruby/site_ruby/1.8/i686-linux/RMagick.so (LoadError)
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/local/lib/ruby/site_ruby/1.8/RMagick.rb:11
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /var/www/cgi-bin/nikki.cgi:9
[Sun May 9 10:31:27 2010] [error] [client 172.16.0.229] Premature end of script headers: /var/www/cgi-bin/nikki.cgi
そこで次のコマンドを実行
chcon -c -v -R -u system_u -r object_r -t textrel_shlib_t /usr/local/lib/ruby/site_ruby/1.8/i686-linux/RMagick.so
「textrel_shlib_t」のところは、「shlib_t」「lib_t」の場合もあるらしい。



prototype.js + ruby + rmagick でファイルアップロード No3

2011-03-09 16:53:33 | プログラム
---------rubyソース upload.cgi -------------
#!/usr/local/bin/ruby -Ku
# ファイルアップロードのためのCGI

# javascript ozUpload.js, ozUpload.css と共に使う
#  prototype.js も必要 (1.6以上)
# 必要な追加ライブラリ RMagick,json
# 対応 画像フォーマット Jpeg,GIF,PNG

require "rubygems"
require 'RMagick'
include Magick
require "json"
require "cgi"

######################################################
# 以下の3つの保存ディレクトリを指定
# アップロード経過(%) を保存するディレクトリ 
#この中にマジックナンバーの名前でファイルを作る
$tempdir='/tmp/uploadcgi'
#画像保存ディレクトリ Webサーバーが書き込み権限を有すること
#  サーバーディレクトリ
$imgdir='/var/www/html/img-post/001/'
# $imgdir の ウエブディレクトリ
$wwwimgdir='/img-post/001/'
######################################################

#置き換えのための文字列
$responsJson='%==responsJson==%'
$uploadIdSub='%==uploadIdSub==%'

# 画像アップ時 返すHTML
# このHTMLは親ウインドウ内のiframeにロードされる。
# HTMLロード後親ウインドウのアップロード完了後ファンクションを呼び出す。
$resHTML= <<EOL
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script>

function addEvent(obj, evType, fn){
    if (obj.addEventListener){obj.addEventListener(evType, fn, true)}
    if (obj.attachEvent){ obj.attachEvent("on"+evType, fn)}
}
function init(){
window.parent.temp_oz_json=#{$responsJson};
eval('window.parent.oz_firstfunc(window.parent.temp_oz_json)');
eval('window.parent.ozUploadhash.#{$uploadIdSub}.postfunc(window.parent.temp_oz_json)');
eval('window.parent.ozUploadhash.#{$uploadIdSub}.afterfunc(window.parent.temp_oz_json)');
}
addEvent(window,'load',init);

</script>
</head>
<body>
</body>
</html>
EOL

##########################################################
#ajaxとして出力する
##########################################################
#戻り値なし
#  body: ajaxとして出力する内容
def ajaxout(body)
    CGI.new.out(
        {"type"=>"text/javascript","charset"=>"UTF-8","language"=>"ja"}
    ){
        "\xef\xbb\xbf"+body
    }
end

##########################################################
#jsonデータとして出力する
##########################################################
#戻り値なし
#  hash: jsonデータとして出力するhashデータ
def jsonout(hash)
    CGI.new.out(
        {"type"=>"text/javascript+json","charset"=>"UTF-8","language"=>"ja"}
    ){
        "(%s)"%[hash.to_json]
    }
end

##########################################################################
#メインクラス
#  javascriptでこのCGIを実行するには
#  1. 同期Ajax URLパラメータで cmd=getmagick でマジックナンバーを取得
#  2. アップロードフォームsubmit()
#       enctype='multipart/form-data' method='post' target='body内のiframe'
#     
#
##########################################################################
class OzMain
    #######################################################
    # オブジェクト初期化
    # CGIパラメータcmdを解析して処理を振り分け
    #######################################################
    def initialize
        @cgi = CGI.new
        @cmd = "#{@cgi['cmd'].to_a.first}"
        @cmd = 'start' if @cmd.empty?
        __send__("cmd_#{@cmd}")
    end #def initialize
    
    #######################################################
    # 実行本体
    # CGIパラメータcmdを解析して処理を振り分け
    #######################################################
    def cmd_start
        hash={}

        #アップロードファイルサイズ最大バイト数
        max_file_size= @cgi.include?('max_file_size') ? @cgi['max_file_size'].read.to_i : 10000
        max_file_size*=1000
        #画像がURLエンコードされたサイズ、さらに他のパラメータのデータサイズもあるので
        #かなり大雑把だけれども content_lengthから1000引いた数値をファイルサイズと仮定する
        data_length=@cgi.content_length -1000 
        hash[:stat]=false
        hash[:img_format]=@cgi['img_format'].read
        if !imgformatcheck(@cgi.params['oz_file1'][0].content_type,hash[:img_format]) then
            hash[:message]="アップロード可能なファイルは"+hash[:img_format]
        elsif max_file_size<data_length then
            hash[:message]="ファイルサイズが大きすぎます(サイズ誤差あり) >#{(max_file_size/1000).to_s}Kbytes"
        else
            begin
                hash[:sessionkey]=@cgi['magickno'].read
                fpath=$tempdir+'/'+hash[:sessionkey]
                img=readimage(data_length,fpath)
                saveimage(img,hash[:sessionkey],hash)
                hash[:stat]=true
            rescue
                hash[:message]="システムの不具合で保存できませんでした。"
            end
        end
        hash[:destform]=@cgi['destform'].read
        hash[:uploadid]=@cgi['uploadid'].read
        hash[:no_output2]=((@cgi['no_output2'].read).to_s.match(/true/i)!=nil)
        outHTML(hash)
    end
    
    # imgformatの中にtargetが示す画像フォーマットが含まれるか調べる
    # contenttype に入っているのは image/pjpeg,image/gif, image/x-png など
    #  含まれるとき 数値 含まれないとき nil
    def imgformatcheck(contenttype,imgformat)
        imgformat.upcase.sub('JPG','JPEG').gsub(',',' ').split.each{|e| break if contenttype=~/#{e}/i}
        $&
    end
    
    def mksessionfile(fpath)
        Dir.mkdir($tempdir) if !FileTest.exist?($tempdir)
        File.open(fpath,'w'){|f| f.puts 0}
    end
    
    #画像データを読み込み シリアル番号名のファイル(fpath)に読み込み残り割合を
    #百分率整数で保存 読み込み終了時にシリアル番号名のファイルは削除する
    def readimage(data_length,fpath)
        xdata=[]
        data=@cgi.params['oz_file1'][0]
        remlen=data_length
        bufsize=1024 #1回で読み込むサイズ
        while !data.eof
            xdata<<data.read(bufsize)
            File.open(fpath,'w'){|f|
                f.puts(100-(remlen.to_f/data_length*100).to_f)
            }
            remlen-=bufsize
            sleep 0.0001      #プログレスバーが見えないので
        end
        File.delete(fpath)
        xdata.join
    end
    
    # サムネイルと元画像(ただし制限より大きいときは縮小したもの)をファイル保存する
    def saveimage(data,fserial,hash)
        #サムネイルのサイズ thumbnail_sizeにはいる様に作成する
        thumbnail_size=@cgi.include?('thumbnail_size') ? @cgi['thumbnail_size'].read.to_i : 100
        #画像の一辺最大サイズ このサイズより大きい場合はこのサイズに縮小する
        max_image_size=@cgi.include?('max_image_size') ? @cgi['max_image_size'].read.to_i : 4000

        #アニメーションGIFに対応するためImageListに読み込む
        imgs=Magick::ImageList.new
        #Imageオブジェクトに画像データを読み込み
        imgs.from_blob(data)
        img=imgs.first
        imgcols=img.columns
        imgrows=img.rows
        hash[:shrink]=false
        #画像があまりにも大きいときmax_image_sizeに入りきるサイズまで縮小する
        if img.columns>max_image_size or img.rows>max_image_size then
            #サイズ最大制限 ジオメトリは '9999x9999'のように文字列
            sizex='%dx%d'%[max_image_size,max_image_size]
            #ジオメトリにあわせて(指定サイズに入るように)画像をリサイズ
            imgs.each{|img|
                img.change_geometry(sizex){|cols, rows, img2| 
                    #img2 の実体はimg なのでimg自体が縮小される
                    img2.resize!(cols, rows)
                    imgcols=cols
                    imgrows=rows
                }
            }
            hash[:shrink]=true
        end
        #保存画像のサイズをhashに入れる
        hash[:imgwidth]=img.columns
        hash[:imgheight]=img.rows
        # jpeg,png,gif 形式を取得して小文字へ
        ext=img.format.downcase
        ext='jpg' if ext=='jpeg'
        #大きい画像を保存
        hash[:imgpath]=$wwwimgdir+fserial+'.'+ext
        imgs.write($imgdir+fserial+'.'+ext)
        
        hash[:redundant]=true
        # サムネイル アニメーションGIFのときは最初の1枚のみにする
        if img.columns>thumbnail_size or img.rows>thumbnail_size then
            #サイズ最大制限 
            sizex='%dx%d'%[thumbnail_size,thumbnail_size]
            #ジオメトリにあわせて(指定サイズに入るように)画像をリサイズ
            img.change_geometry(sizex){|cols, rows, img2|
                img2.resize!(cols, rows)
            }
            hash[:redundant]=false
        end
        #サムネイルのサイズをhashに入れる
        hash[:thumbwidth]=img.columns
        hash[:thumbheight]=img.rows
        #縮小画像を保存
        hash[:thumbpath]=$wwwimgdir+fserial+'-mini.'+ext
        img.write($imgdir+fserial+'-mini.'+ext)
    end
    
    #画像アップロードの結果を返す。
    #bodyに結果HashをURIエスケープして返す。返した内容でOnloadイベントで
    def outHTML(hash)
        hash[:outputid1]=@cgi['oz_output1'].read
        hash[:outputid2]=@cgi['oz_output2'].read
        $resHTML.gsub!($uploadIdSub,hash[:uploadid])
        $resHTML.sub!($responsJson,hash.to_json)
        @cgi.out('text/html'){$resHTML}
    end
    
    #アップロードする前にこのパラメータで呼ばれて、セッションIDのようなマジックナンバーを返す。
    def cmd_getmagick
        magickno='%d%4.4d'%[Time.now.to_i,rand(10000)] #少しでも複雑にするため
        mksessionfile($tempdir+'/'+magickno)
        ajaxout(magickno)
    end
    # プログレスバー このパラメータでアップロードが完了するまで何度も呼ばれる
    # このHashはURIエスケープしない
    def cmd_progressbar
        fpath=$tempdir+'/'+@cgi['magickno']
        hash={:stat=>false}
        begin
            File.open(fpath,'r+'){|f| 
                hash[:progress]=f.read.to_s.to_f
            }
            hash[:stat]=true
        rescue
        end
        jsonout(hash)
    end
end

OzMain.new
------------ upload.cgi おわり ----------


prototype.js + ruby + rmagick でファイルアップロード No2

2011-03-09 16:07:13 | プログラム
-------------------  ozUpload.js  ------------------
/******************************************************************************
プログレスバー付き画像ファイルアップロード 画像保存とサムネイル保存
  (このファイルはUTF8で保存すべし)HTML,css ファイルもUTF8じゃないとだめだと思う
  
  自動的に作成されるファイルアップロード入力領域
  +------------------------------------------------------+
  |+---- fileInput ------+                               |
  |+---------------+ +------------------------------+    |
  || progressbar   | |                              +    |
  ||               | |                              +    |
  ||    output1    | |            output2           +    |
  ||               | |                              +    |
  |+---------------+ +------------------------------+    |
  +------------------------------------------------------+
  
使い方 ozUpload(uploadid,action,option)
 パラメータ
  uploadid: 必須 アップロード用inputが表示される領域のID(文字列)
  action: 必須 uploadサーバー側CGIURL(文字列)
  option:オプション {'オプション名':値, ....}
        max_file_size  自然数default:3000 アップロードファイルの最大サイズKbytes
        thumbnail_size 自然数default:120 サムネイルの一辺サイズ
        max_image_size 自然数default:1200
                画像の最大サイズ(これより大きいときはこのサイズに縮小して保存
        output1_html   ファイル参照の下左側領域に初期表示するHTML
        output2_html   ファイル参照の下右側領域に初期表示するHTML
        postfunc       アップロード完了後に実行する関数
                       postfunc: postfunc1   としたときpostfunc1(json) で定義する
                       指定しなければoz_postedupload(json)が実行される。
        afterfunc      postfunc またはデフォルトpostfuncが実行された後実行するFunction
                       パラメータはpostfuncと同じ afterfunc(json)を定義する。
        no_output2     postfuncが指定されていないときoutput2(出力領域右側)へ出力しない true false
                       default false
        img_format     アップロードできる画像フォーマット default: 'jpeg,gif,png'
                       'jpeg,png' と指定すればgifは使えない
                       'jpeg' , 'jpg' どちらも可
                   
アップロードが完了するとuploadidの先祖であるFormに
hidden属性のInputタグimgpath_xxxとthumbpath_xxxが追加され
その値はそれぞれアップロードされた画像とサムネイルのwwwpathが設定される。
xxxはozUpload()のuploadid
(imgpath_xxxとthumbpath_xxxはアップロードが成功したタイミングでinput hiddenタグが追加されるので、アップロードしないときは存在しない)


使用例
-- htmlヘッダー部 --
<link href="ozUpload.css" rel="stylesheet" type="text/css">
<script src="prototype.js" type="text/javascript"></script>
<script src="ozUpload.js" type="text/javascript"></script>
<script>
//最もシンプルな呼び出し方
//ozUpload('uploadarea','/cgi-bin/upload.cgi');

//アップロード完了時起動Functionを自分で定義する。3番目のパラメータ指定
//その他オプションを指定するときは4番目をハッシュで指定
ozUpload(
    'uploadarea',
    '/cgi-bin/upload.cgi',
    {
        postfunc:自分で操作するFunction,
        max_file_size:40,
        output2_html:'ここに何かを表示する<br>..........'
    }
);
</script>
-- body部 --
<form name='xxxx'>
.........
........
<div id='uploadarea'></div>
<input ......>
</form>
*****************************************************************************/

/* 外部からはこの関数をコールすることで機能を実現する */
function ozUpload(uploadid,action,option)
{
    if(!ozUploadhash[uploadid]){ozUploadhash[uploadid]={init:false};}
    ozUploadhash[uploadid].uploadid=uploadid;
    ozUploadhash[uploadid].postfunc=oz_postedupload;
    ozUploadhash[uploadid].afterfunc=oz_afterfunc;
    oz_cgiurl=action;
    for(i=0;i<oz_uploadinitnm.length;i++){
        if(option!=undefined && option[oz_uploadinitnm[i][0]]){
            ozUploadhash[uploadid][oz_uploadinitnm[i][0]]=option[oz_uploadinitnm[i][0]];
        }
    }
}

//アップロード完了時実行Function  
//  ozUpload()のoptionでpostfunc を指定しないときこのFunctionが実行される。
//    ユーザーが独自のアップロード完了時実行Functionを定義するときはこのFunctionを参考に
//    独自名で function xxxxx(json){} として作成する。
//    ozUpload()のoptionに postfunc:'xxxxx' と指定する。
//
//  アップロード完了後サーバーにより以下の各種データがJSON形式で設定されてくる。
//  パラメータ json
//  json.stat      成功:true  失敗:false
//  json.message   失敗したときの理由 (日本語メッセージ)
//  json.outputid1 出力欄ID
//  json.outputid2 出力欄ID
//  json.imgpath   保存した画像のwwwパス
//  json.thumbpath サムネイルのwwwパス
//  json.imgwidth  保存した画像の横pixcel
//  json.imgheight 保存した画像の縦pixcel
//  json.thumbwidth  サムネイルの横pixcel
//  json.thumbheight サムネイルの縦pixcel
//  json.shrink    最大一辺より大きいため保存画像は縮小された true false
//  json.redundant 画像サイズがサムネイル一辺より
//                 小さいためサムネイルと元画像が同じ         true false
//  json.uploadid  アップロードパーツが載るエレメントID
//                 ozUpload() の第一引数で与えた値
//  json.destform  このアップロードエレメントが乗っているForm.name
function oz_postedupload(json)
{
    if(!json.stat){
        $(json.outputid1).innerHTML=json.message;
        if(!json.no_output2){$(json.outputid2).innerHTML='';}
    }else{
        if(json.redundant){
            $(json.outputid1).innerHTML=
            "<img src='"+json.thumbpath + "'  border=0>";
        }else{
            $(json.outputid1).innerHTML=
            "<a href='"+json.imgpath+"' target='_blank'>"+
            "<img src='"+json.thumbpath + "'  border=0>"+
            "</a>";
        }
        if(!json.no_output2){
            $(json.outputid2).innerHTML=
            (json.shrink?"大きいため縮小されました<br>":"")+
            (json.redundant?"元画像が小さいためサムネイルはありません。":"画像をクリックすると大きい画像サイズウインドウを開きます。")+"<br>"+
            '保存画像:&nbsp;W'+json.imgwidth+'pix,&nbsp;H'+json.imgheight+'pix<br>'+
            json.imgpath+'<br>'+
            'サムネイル:&nbsp;W'+json.thumbwidth+'pix,&nbsp;H'+json.thumbheight+'pix<br>'+
            json.thumbpath;
        }
    }
}
/*
upload完了後最初に実行するFunction
このFunctionはアップロード完了後に自動的にCallされ、次の動作をする。
ファイル選択をenableにする。
プログレスバーを不可視にする。
ファイルアップロード用Element xxxが置いてあるFormに
<input type='hidden' name='imgpath_xxx'>
<input type='hidden' name='thumbpath_xxx'>
このフォームエレメントが存在しない場合にはエレメントを追加する。
値はアップロードした画像のWWWパスが設定される。
*/
function oz_firstfunc(json)
{
    $(ozUploadhash[json.uploadid]['fileinputid']).disabled=false;
    var progressbardiv='progressbardiv_'+$(json.uploadid).id;
    $(progressbardiv).style.display='none';
    $(json.outputid1).style.visibility='visible';
    var imgpath='imgpath_'+json.uploadid;
    var thumbpath='thumbpath_'+json.uploadid;
    var destform=document.forms[json.destform];
    if(json.stat){
        if(destform){
            if(!destform.elements[imgpath]){
                destform.insert("<input type='hidden' name='"+imgpath+"'>");
            }
            destform.elements[imgpath].value=json.imgpath;
            if(!destform.elements[thumbpath]){
                destform.insert("<input type='hidden' name='"+thumbpath+"'>");
            }
            destform.elements[thumbpath].value=json.thumbpath;
        }
    }else{
        if(destform.elements[imgpath]){destform.elements[imgpath].value='';}
        if(destform.elements[thumbpath]){destform.elements[thumbpath].value='';}
    }
}
/* dummy */
function oz_afterfunc(json){}
//
function oz_uploadfile(uploadform,uploadid)
{
    var upload_area=$(uploadid);
    var progressbardiv='progressbardiv_'+upload_area.id;
    var progressbarinnerdiv='progressbarinnerdiv_'+upload_area.id;
    var progresstext='progresstext_'+upload_area.id;
    var oz_retdiv='oz_retdiv_'+upload_area.id;
    var myform=$(uploadform);
    $(progressbardiv).style.display='block';
    $(progressbarinnerdiv).style.width="100%";
    $(progresstext).innerHTML='preparing...'
    $(oz_retdiv).style.visibility='hidden';
    //ファイルアップロードの前にセッションキーとしてのマジックナンバーを同期Ajaxで取得
    var myAjax = new Ajax.Request(
        oz_cgiurl,
        {
            method: 'post',
            parameters: "cmd=getmagick",
            asynchronous: false
        }
    );
    magick_no=myAjax.transport.responseText;
    myform.elements['magickno'].value= magick_no;
    myform.action=oz_cgiurl+'?'+magick_no;//キャッシュ対策
    myform.submit();//targetがiframeなのでsubmit後次の行へすぐ行く
    ozUploadhash[uploadid].progress=0;
    myform.oz_file1.disabled=true;
    oz_progressbar(magick_no,uploadid,myform.name);//プログレスバー表示
}

var counter=0;
function oz_progressbar(magick_no,uploadid,formname)
{
    var upload_area=$(uploadid);
    var progressbardiv='progressbardiv_'+upload_area.id;
    var progressbarinnerdiv='progressbarinnerdiv_'+upload_area.id;
    var progresstext='progresstext_'+upload_area.id;

    new Ajax.Request(
        oz_cgiurl,
        {
            method: "post",
            /* キャッシュ対策のためURLを毎回変えるため日付シリアルを付ける */
            parameters: "cmd=progressbar&magickno="+magick_no +"&"+new Date().getTime(),
            onSuccess: function(httpObj){
                var json = eval(httpObj.responseText);
                if(json.stat){
                    // json.progressには読み込み済み割合数がはいっている
                    //   この非同期Ajaxが後発よりレスポンスが遅いときがある。
                    //   着順が逆になってprogressが減ったときは表示更新しない
                    if(ozUploadhash[uploadid].progress<json.progress){
                        ozUploadhash[uploadid].progress=json.progress;
                        progressi=parseInt(json.progress);
                        $(progressbarinnerdiv).style.width=(100-progressi)+"%";
                        $(progresstext).innerHTML='Loading...&nbsp;'+progressi+"%";
                    }
                    /* インターバル0.2秒で自身Functionを再実行 */
                    setTimeout("oz_progressbar('"+magick_no+"','"+uploadid+"','"+formname+"')", 200);
                }else{
                    $(progressbarinnerdiv).style.width="0%";
                    $(progresstext).innerHTML="Completed..100%";
                }
            },
            onFailure: function(httpObj){
                alert('upload エラー');
            }
        }
    );
}

function oz_init2(hash)
{
    var upload_area=$(hash['uploadid']);
    var oz_uploaddiv='oz_uploaddiv_'+upload_area.id;
    var uploadform='uploadform_'+upload_area.id;
    hash['thisform']=uploadform;
    hash['fileinputid']='file_'+uploadform;
    var iframe_oz='iframe_oz_'+upload_area.id;
    $(document.body).insert(
    "<div id='"+oz_uploaddiv+"' class='oz_uploaddiv'>"+
    "<form id='"+uploadform+"' name='"+uploadform+"'>"+
    "<input type='file' name='oz_file1' "+
    "id='"+hash['fileinputid']+"' "+
    "  onchange='oz_uploadfile(&quot;"+uploadform+"&quot;,&quot;"+upload_area.id+"&quot;)'>"+
    "</form>"+
    "</div>"
    );
    var myform=$(uploadform);
    $(document.body).insert("<iframe name='"+iframe_oz+"' style='display:none;'></iframe>");

    oz_uploadinitnm.each(
        function(val,idx){
            if(val[1]!='onlyhash'){
                myform.insert({top:"<input type='hidden' name='"+ val[0]+"'>"});
            }
        }
    );
    
    if(upload_area.up("form")){
        myform.destform.value=upload_area.up("form").name;
    }
    var oz_output1='oz_retdiv'+'_'+upload_area.id;
    var oz_output2='oz_resultsub'+'_'+upload_area.id;
    myform.insert({top:"<input type='hidden' name='oz_output1' value='"+oz_output1+"'>"});
    myform.insert({top:"<input type='hidden' name='oz_output2' value='"+oz_output2+"'>"});
    myform.insert(
        "<div id='progressbarbase_"+upload_area.id+"' class='progressbarbase'>"+
        "<div id='progressbardiv_"+upload_area.id+"' class='progressbardiv'>"+
        "<div id='progressbarinnerdiv_"+upload_area.id+"' class='progressbarinnerdiv'></div>"+
        "<div id='progresstext_"+upload_area.id+"' class='progresstext'></div>"+
        "</div>"+
        "</div>"+
        "<div style='position:relative;'>"+
        "<div id='"+oz_output1+"' class='oz_retdiv'></div>"+
        "<div id='"+oz_output2+"' class='oz_resultsub'></div>"+
        "</div style='clear:left;'>"
    );
    myform.method='post';
    myform.action=oz_cgiurl;
    myform.encoding='multipart/form-data';
    myform.target=iframe_oz;

    var pos=Position.cumulativeOffset(upload_area);
    $(oz_uploaddiv).style.top=pos.top+1;
    $(oz_uploaddiv).style.left=pos.left+2;
    
    // 以下 option 指定がないときのデフォルト値を設定
    $(oz_output1).innerHTML='upload完了後画像サムネイルがここに表示されます。';
                                //アップ後サムネイルを表示する領域
    $(oz_output2).innerHTML='';
                                //アップ後何がしかを表示する領域
    myform.max_file_size.value=3000;    //最大ファイルサイズKbytes
    myform.max_image_size.value=1200;    //画像1辺の長さがこれ以上のときこのサイズにリサイズして保存
    myform.thumbnail_size.value=120;    //サムネイル1辺の長さ
    myform.img_format.value='jpeg,gif,png';
    myform.no_output2.value=false;
    //デフォルト値設定終わり
    
    //アップロード領域のdiv id を設定
    myform.elements['uploadid'].value=upload_area.id;
    //
    for(i=0;i<oz_uploadinitnm.length;i++){
        if(hash[oz_uploadinitnm[i][0]]){
            if(oz_uploadinitnm[i][1]=='elem'){
                myform.elements[oz_uploadinitnm[i][0]].value=hash[oz_uploadinitnm[i][0]];
            }else if(oz_uploadinitnm[i][1]=='html'){
                $(eval(oz_uploadinitnm[i][2])).innerHTML=hash[oz_uploadinitnm[i][0]];
            }
        }
    }
    $(oz_output1).style.width=myform.thumbnail_size.value;
    $(oz_output1).style.height=myform.thumbnail_size.value;
    $(oz_output2).style.height=myform.thumbnail_size.value;

}
function oz_initupload()
{
    var hash;
    for(key in ozUploadhash){
        if(!ozUploadhash[key]['init']){
            hash=ozUploadhash[key];
            hash['init']=true;
            oz_init2(hash);
        }
    }
}
Event.observe(window,'load',oz_initupload);

var ozUploadhash={};
/* RubyCGIのURL ozUpload()のパラメータで設定される
var oz_cgiurl="";

/* ozUpload()のoption Hashの名称についての配列
  配列の一要素中の配列について
    第一要素 option Hashの名称 <input type='hidden' name='xxx'> のxxxになる。
    第二要素 種類 'elem': <input type='hidden' name='xxx'>のvalueに
                ozUploadhashの同名のキーの値を代入する。
            'html': HTML要素で このとき第三要素が付く。
            'onlyhash': ozUploadhash[xxx][xxx]になるだけでElementには作成されない。
    第三要素 「種類」がHTMLのとき function oz_initupload()内の
          xxx.innerHTML に入れるため xxx変数の変数名evalするため
*/
var oz_uploadinitnm=[
    ['magickno',''],
    ['destform',''],
    ['uploadid',''],
    ['postfunc','onlyhash'],
    ['afterfunc','onlyhash'],
    ['no_output2','elem'],
    ['max_file_size','elem'],
    ['thumbnail_size','elem'],
    ['max_image_size','elem'],
    ['img_format','elem'],
    ['output1_html','html','oz_output1'],
    ['output2_html','html','oz_output2']
];

--------- ozUpload.js おわり -------------

prototype.js + ruby + rmagick で画像アップロード No1

2011-03-09 15:58:03 | プログラム
久しぶりにポスト

画像アップロードライブラリをあちこち探してみましたが、
うまく動かなかったり、で、自分でゼロから作ることにした。

プログレスバー付き、
サムネイルを保存、
最大サイズを決めてアップロードした画像が大きければリサイズする。

IE6,IE8,Firefoxで確認 safari が動かない???

PHPならすぐ出来るみたいだけれど、
Ajax でファイルアップロードを実現するためにかなり時間がかかってしまったが、そこそこに出来たと思う。
細かいところ、まだバグはあるかもしれないが、なかなかかっこいい。

 

HTMLで必要なライブラリは prototype.js
ruby 必要なライブラリは 
        json
    Rmagick(これ結構インストールではまることある jpeg,gif,png 対応必要)

サンプルHTML      ozUploadTest.htm   このページ
スタイルシート    ozUpload.css       このページ
Javascriptソース ozUpload.js        次
Rubyソース        upload.cgi         次の次
プログレスバー用GIF    <--- ozUpload.cssの.progressbardivのbackground-image:url(/images/barbar.gif);を保存したディレクトリに調整のこと

サンプルHTMLソース ozUploadTest.htm
-----------------------------------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--
画像アップロード 使い方
javascriptライブラリ prototype.js 1.6以上
日本語円コーディングは UTF8

最も単純な使い方は
HTML body 内に<div id='uploadarea'></div>を記入
head内スクリプトで次の1行
ozUpload('上のフォームエレメントID','サーバー受け側CGIのURL');
-->

<link href="ozUpload.css" rel="stylesheet" type="text/css">
<script src="xxxxxx/prototype.js" type="text/javascript"></script> <!--- ディレクトリ調整必要 -->
<script src="xxxxxx/ozUpload2.js" type="text/javascript"></script> <!--- ディレクトリ調整必要 -->
<script>
function uploadfunc(json)
{
    //ozUpload.js内のfunction ozpostedupload(json) を参考に処理を行う
    $(json.outputid1).style.visibility='visible';
    if(!json.stat){
        $(json.outputid1).innerHTML=json.message;
    }else{
        $(json.outputid1).innerHTML=
        "<a>"+
        "<img>"+
        "</a>";
        $(json.outputid2).innerHTML='これは独自ハンドラです'+json.uploadid +''+
        (json.shrink?"大きいため縮小されました":"");
    }
}
function afterfunc1(json)
{
    $(json.outputid2).innerHTML='After Func 実行'+json.thumbpath;
}
var cgiurl='/cgi-bin/upload.cgi';
//最も単純な呼び出し
ozUpload('uploadarea',cgiurl);
//アップロード完了後独自Function実行
ozUpload('uploadarea3',cgiurl,{postfunc:uploadfunc});
//いろいろなパラメータ設定
ozUpload(
    'uploadarea2',
    cgiurl,
    {
        max_file_size:200,
//        postfunc:uploadfunc,
        afterfunc:afterfunc1,
        img_format:'jpeg,gif',
        no_output2:true,
        output2_html:"<div>aaaacccc<h2>xxx</h2></div>"
    }
);

</script>
<style>
.uploadarea{
    width:600px;
    height:160px;
}
</style>
</head>
<body>
 <form name='f1'>
  <table>
   <tr><th>no1</th><th>no2</th><th>no3---</th></tr>
   <tr><td>aaaaa</td><td>bbbbbbb</td><td>cccccccdddddcc</td></tr>
   <tr><td>1111</td><td>2222</td><td>333</td></tr>
   <tr><td> <div>&nbsp;</div></td></tr>
   <tr><td> <div>&nbsp;</div></td></tr>
   <tr><td> <div>&nbsp;</div></td></tr>
  </table>
 </form>
</body>
</html>


------------------- ozUpload.css おわり --------------------

文字数が多くなるので
Javascriptソース ozUpload.js と
Rubyソース upload.cgi はそれぞれ別にアップ





TInterfacedObject freeしちゃだめ?

2006-11-15 18:15:46 | プログラム
先の 「TWebBrowser イベントを拾う方法 」のなかで

htmlDoc.onmouseover := (TEventObject.Create(Document_OnMouseOver) as IDispatch) ;
としてマウスオーバーのイベントハンドラを作っているけれども、
CreateしたものをFreeしていない。
おかしい、とおもって、Freeしてやったら、エラー
おやおや。


http://www.kcat.zaq.ne.jp/takao/diary/diary.200203.html#3
2002/3/3 の記事

なるほどそういうわけなんですね。

賢い人いるんですね。
Delphi は難しい。