ajax上傳圖片文件

這裏用的是一個隱藏的iframe,這樣可讓form表單提交到這個iframe裏面,用戶就看不到頁面的刷新了javascript

 

 

前段時間在解決ajax上傳文件時折騰了好一陣。直接用$.post上傳文本信息確定是沒有問題的。可是$.post直接上傳圖片是不可行的。php

後來看到網上的一些解決方案,有現成的ajax上傳文件的封裝的方法也有利用flash的。flash確實是個好方法 可是不是每一個人都會flash的並且下載下來現成的方法要作修改也不是件易事,且文件相對較大。html

最後只好模擬iframe來實現。發現至關的簡單。java

<iframe name="ajaxUpload" style="display:none"></iframe>jquery

<form name="from1" id="from1" method="post" action="url"  enctype="multipart/form-data" target="ajaxUpload">     這裏是重點。要上傳文件enctype這個屬性不可少,target的值改成iframe的name的值。ajax

<table>數組

   <tr>瀏覽器

      <td>附件:</td>app

      <td><input type="file" id="document" name="document"/></td> 框架

   </tr> 

</table> 

</form>

 

上面是HTML

下面寫一下js代碼,我是用的jQuery因此在用的時候載入jquery的庫是必不可少的。

 $(function(){

        if($.browser.msie){

             window.form1.submit();}else{

             $("#form1").submit();}

       });

 //這裏是作了一個瀏覽器版本的判斷,由於IE是不太符合規範的一個瀏覽器,尤爲是IE6。IE6是不直接支持$("#idName").submit();這種方式的。

而後在服務端要怎麼着呢,並且還得返回一個值,直接submit是沒法返回值的

public void Upload()

{

    HttpPostedBase ff=Request.Files["document"];//這裏是獲取上傳的文件流,也能夠用索引值來表示若是是多個文件的話

   string fileName=System.DateTime.Now+ff.FileName.ToString();   //這裏取出來的文件名是沒有後綴的,因此要保存的話還須要取出文件拓展名。這裏就不寫過細,只是爲描述這樣一個思路。

    try{

          SaveAs(documentPath+fileName+extendtionName); 

           Response.Write("<script type='text/javascript' type='language'>parent.window.callBackMethod('上傳成功');</scrpt>");

       } 

     catch

     {

       Response.Write("<script type='text/javascript' type='language'>parent.window.callBackMethod('上傳失敗');</scrpt>");  //parent.window.methodName();這個是JS調用父頁的方法。由於如今模擬一個iframe上傳文件,這個iframe的做用就是一箇中間站的做用。在父頁點擊上傳後經過target會將頁面文檔流傳入iframe中再上傳服務端做處理。服務端有響應以後而後再在iframe裏面顯示出來,而不是直接在父頁面顯示出結果。這裏可能就是一個alert()彈出一個對話框提示一下,若是是這樣那麼不調父頁方法也行。若是想把這提示的內容豐富一點好比彈出個相似人人網的藍色的對話框之類的。

     } 

 模擬iframe實際上是頁面局部更新,可是頁面中的這個iframe沒有內容並且仍是不顯示的,因此它刷新了徹底不會影響到整個頁面。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

最近看了一些jQuery即時上傳的插件,總算看懂了些門路。現將其最爲核心的一部分抽取出來,以期用最簡單的例子來講明jQuery圖片即時上傳的原理。

  首先本用例一共包含3個文件:

    一、上傳面板HTML文件。

    二、上傳處理PHP文件。

    三、jQuery庫。

  第1、上傳面板HTML文件(index.html)。

           其主要包含了jQuery庫、即時上傳所需js、表單和iframe框架。下面是其源碼,其中已附詳細註釋。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>jQuery Upload Image</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Language" content="zh-CN" />
    <!--<script type="text/javascript" src="jquery-1.6.2.min.js"></script>-->    <!-- 本地jquery庫-->
    <script type="text/javascript" src="http://files.cnblogs.com/Zjmainstay/jquery-1.6.2.min.js"></script>
</head>
<body>
<style>
    #exec_target{display:none;width:0;height:0;}
    #feedback{width:1200px;margin:0 auto;}
    #feedback img{float:left;width:300px;height:300px;}    
</style>
<script type="text/javascript">
$(document).ready(function(){
    //選擇文件成功則提交表單
    $("#upload_file").change(function(){
        if($("#upload_file").val() != '') $("#submit_form").submit();
    });
    //iframe加載響應,初始頁面時也有一次,此時data爲null。
    $("#exec_target").load(function(){
        var data = $(window.frames['exec_target'].document.body).find("textarea").html();
        //若iframe攜帶返回數據,則顯示在feedback中
        if(data != null){
            $("#feedback").append(data.replace(/&lt;/g,'<').replace(/&gt;/g,'>'));
            $("#upload_file").val('');
        }
    });
});
</script>
<form id="submit_form" method="post" action="submit_form_process.php" target="exec_target" enctype="multipart/form-data">
    <input type="file" name="upload_file" id="upload_file">        <!-- 添加上傳文件 -->
</form>
<iframe id="exec_target" name="exec_target"></iframe>    <!-- 提交表單處理iframe框架 -->
<div id="feedback"></div>    <!-- 響應返回數據容器 -->
</body>
</html>

第2、上傳處理PHP文件(submit_form_process.php)。

    其主要包含了圖片文件的簡單上傳,及返回圖片標籤<img>,其中存儲剛上傳的圖片。下面是其源碼。

<?php
    //header('content-type:text/html charset:utf-8');  /* 這句要刪除,不然可能會致使IE下回傳HTML變成下載 */
    //不存在當前上傳文件則上傳
    if(!file_exists($_FILES['upload_file']['name'])) move_uploaded_file($_FILES['upload_file']['tmp_name'],iconv('utf-8','gb2312',$_FILES['upload_file']['name']));
    //輸出圖片文件<img>標籤
    echo "<textarea><img src='{$_FILES['upload_file']['name']}'/></textarea>";
//End_php

總結之原理透析:

    講到jQuery即時上傳,不知道其原理的人第一想法通常都是使用AJAX(補註:當時不知道有FormData對象),我也嘗試過。可是,因爲上傳文件不一樣於通常數據的POST,它須要表單form的提交來完成。所以,jQuery上傳插件也是將<input type="file">的數據轉至一個新生的form當中將其提交,而表單的target指向新生的iframe,在iframe中作表單提交後的處理,完成後iframe會從新加載幷包含處理結果,經過iframe的load事件即可捕捉並獲取處理結果,回傳至原表單所在的頁面(feedback)中,實現jQuery即時上傳的效果。而在表單提交的時候,爲了實現選擇文件後即時提交表單,則使用了input標籤的change事件(index.html L19-21),只要選擇了文件,input的值就會發生變化,此時就能夠提交表單進行處理了。

軟件包下載:最簡單的jQuery即時上傳示例

 

/***************************************   追加  ***************************************/

受@東方翔 評論提示,測試了一下$.ajax 的FormData對象,而後發現成功了(FF、Chrome測試成功),嘿嘿~下面是源碼,控制文件爲submit_form_process.php不變。

特別的:contentType: false,
            processData: false,

這兩個參數是必須的。

缺乏contentType: false,$_FILES值爲空。

缺乏processData: false,FF控制檯報錯:「NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object」,直接不能運行。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>FormData</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Language" content="zh-CN" />
    <script type="text/javascript" src="http://files.cnblogs.com/Zjmainstay/jquery-1.6.2.min.js"></script>
</head>
<body>
<style>
    #feedback{width:1200px;margin:0 auto;}
    #feedback img{float:left;width:300px;height:300px;}
</style>
<div>
    <!-- 點擊圖片添加文件方式 -->
    <img src="http://f7-preview.awardspace.com/zjmainstay.co.cc/jQueryExample/jquery_upload_image/files/addfile.jpg" onclick="getElementById('inputfile').click()" title="點擊添加圖片" alt="點擊添加圖片">
    <input type="file" name="image" style="opacity:0;filter:alpha(opacity=0);" id="inputfile"/>
</div>
<div id="feedback"></div>    <!-- 響應返回數據容器 -->
<script type="text/javascript">
$(document).ready(function(){
    $("#inputfile").change(function(){
        //建立FormData對象
        var data = new FormData();
        //爲FormData對象添加數據
        //
        $.each($('#inputfile')[0].files, function(i, file) {
            data.append('upload_file', file);
        });
        $.ajax({
            url:'submit_form_process.php',
            type:'POST',
            data:data,
            cache: false,
            contentType: false,    //不可缺
            processData: false,    //不可缺
            success:function(data){
                data = $(data).html();
                if($("#feedback").children('img').length == 0) $("#feedback").append(data.replace(/&lt;/g,'<').replace(/&gt;/g,'>'));
                else $("#feedback").children('img').eq(0).before(data.replace(/&lt;/g,'<').replace(/&gt;/g,'>'));
            }
        });
    });
});
</script>
</body>
</html>

/***************************************   追加2  ***************************************/

多圖上傳實現(獨立於上面兩個版本的文件):

     一、index.html文件

        功能:點擊圖片添加文件、添加多個文件、即時上傳文件、顯示上傳文件反饋信息。

        包含技術:

              1)$.ajax

              2)$.ajax 發送FormData對象

              3)input multiple="multiple"上傳多個文件

              4)img onclick="getElementById('inputfile').click()" 點擊圖片實現添加文件操做

              5)input type="file" 樣式:height:0;width:0;z-index: -1;隱藏添加文件按鈕(Chrome下使用display:none會致使點擊失效)    

         源碼:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Easy Ajax FormData Upload Multiple Images</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Language" content="zh-CN" />
    <script type="text/javascript" src="http://files.cnblogs.com/Zjmainstay/jquery-1.6.2.min.js"></script>
</head>
<body>
<style>
    #feedback{width:1200px;margin:0 auto;}
    #feedback img{float:left;width:300px;height:300px;}
    #ZjmainstaySignaturePicture,#addpicContainer{float:left;width: 100%;}
    #addpicContainer{margin-left:5px;}
    #ZjmainstaySignaturePicture img{width: 535px;}
    #addpicContainer img{float: left;}
    .loading{display:none;background:url("http://f7-preview.awardspace.com/zjmainstay.co.cc/jQueryExample/jquery_upload_image/files/ui-anim_basic_16x16.gif") no-repeat scroll 0 0 transparent;float: left;padding:8px;margin:18px 0 0 18px;}
</style>
<div id="ZjmainstaySignaturePicture"><a href="http://www.cnblogs.com/Zjmainstay"><img src="http://pic002.cnblogs.com/images/2012/383557/2012071311244097.jpg"/></a></div>
<div id="addpicContainer">
    <!-- 利用multiple="multiple"屬性實現添加多圖功能 -->
    <!-- position: absolute;left: 10px;top: 5px;只針對本用例將input隱至圖片底下。-->
    <!-- height:0;width:0;z-index: -1;是爲了隱藏input,由於Chrome下不能使用display:none,不然沒法添加文件 -->
    <!-- onclick="getElementById('inputfile').click()" 點擊圖片時則點擊添加文件按鈕 -->
    <img onclick="getElementById('inputfile').click()" style="cursor:pointer;border: 1px solid #AABBCC;" title="點擊添加圖片" alt="點擊添加圖片" src="http://f7-preview.awardspace.com/zjmainstay.co.cc/jQueryExample/jquery_upload_image/files/addfile.jpg">
    <input type="file" multiple="multiple" id="inputfile" style="height:0;width:0;z-index: -1; position: absolute;left: 10px;top: 5px;"/>
    <span class="loading"></span>
</div>
<div id="feedback"></div>    <!-- 響應返回數據容器 -->
<script type="text/javascript">
$(document).ready(function(){
    //響應文件添加成功事件
    $("#inputfile").change(function(){
        //建立FormData對象
        var data = new FormData();
        //爲FormData對象添加數據
        $.each($('#inputfile')[0].files, function(i, file) {
            data.append('upload_file'+i, file);
        });
        $(".loading").show();    //顯示加載圖片
        //發送數據
        $.ajax({
            url:'submit_form_process.php',
            type:'POST',
            data:data,
            cache: false,
            contentType: false,        //不可缺參數
            processData: false,        //不可缺參數
            success:function(data){
                data = $(data).html();
                //第一個feedback數據直接append,其餘的用before第1個( .eq(0).before() )放至最前面。
                //data.replace(/&lt;/g,'<').replace(/&gt;/g,'>') 轉換html標籤,不然圖片沒法顯示。
                if($("#feedback").children('img').length == 0) $("#feedback").append(data.replace(/&lt;/g,'<').replace(/&gt;/g,'>'));
                else $("#feedback").children('img').eq(0).before(data.replace(/&lt;/g,'<').replace(/&gt;/g,'>'));
                $(".loading").hide();    //加載成功移除加載圖片
            },
            error:function(){
                alert('上傳出錯');
                $(".loading").hide();    //加載失敗移除加載圖片
            }
        });
    });
});
</script>
</body>
</html>

  二、submit_form_process.php後臺處理文件

        功能:對FormData中包含的$_FILES數組作處理並上傳圖片文件,回傳反饋信息。

        包含技術:

             1)FormData提交至$_FILES後的結構形式

             2)iconv('utf-8','gb2312',$filename) 對文件名進行轉碼處理

             3)preg_match("/^\.(jpg|jpeg|gif|png){1}$/i", strrchr($gb_filename, '.')) 文件類型過濾

             4)move_uploaded_file()上傳文件

             5)echo '<textarea><img....<img....</textarea>';回傳反饋信息。

        源碼:

<?php
    header('content-type:text/html charset:utf-8');
    $dir_base = "./files/";     //文件上傳根目錄
    //沒有成功上傳文件,報錯並退出。
    if(empty($_FILES)) {
        echo "<textarea><img src='{$dir_base}error.jpg'/></textarea>";
        exit(0);
    }
    
    $output = "<textarea>";
    $index = 0;        //$_FILES 以文件name爲數組下標,不適用foreach($_FILES as $index=>$file)
    foreach($_FILES as $file){
        $upload_file_name = 'upload_file' . $index;        //對應index.html FomData中的文件命名
        $filename = $_FILES[$upload_file_name]['name'];
        $gb_filename = iconv('utf-8','gb2312',$filename);    //名字轉換成gb2312處理
        //文件不存在才上傳
        if(!file_exists($dir_base.$gb_filename)) {
            $isMoved = false;  //默認上傳失敗
            $MAXIMUM_FILESIZE = 1 * 1024 * 1024;     //文件大小限制    1M = 1 * 1024 * 1024 B;
            $rEFileTypes = "/^\.(jpg|jpeg|gif|png){1}$/i"; 
            if ($_FILES[$upload_file_name]['size'] <= $MAXIMUM_FILESIZE && 
                preg_match($rEFileTypes, strrchr($gb_filename, '.'))) {    
                $isMoved = @move_uploaded_file ( $_FILES[$upload_file_name]['tmp_name'], $dir_base.$gb_filename);        //上傳文件
            }
        }else{
            $isMoved = true;    //已存在文件設置爲上傳成功
        }
        if($isMoved){
            //輸出圖片文件<img>標籤
            //注:在一些系統src可能須要urlencode處理,發現圖片沒法顯示,
            //    請嘗試 urlencode($gb_filename) 或 urlencode($filename),不行請查看HTML中顯示的src並酌情解決。
            $output .= "<img src='{$dir_base}{$filename}' title='{$filename}' alt='{$filename}'/>";
        }else {
            $output .= "<img src='{$dir_base}error.jpg' title='{$filename}' alt='{$filename}'/>";
        }
        
        $index++;
    }
    
    echo $output."</textarea>";
    
//End_php
相關文章
相關標籤/搜索