溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

無刷新上傳文件以及HTML5下的實現(xiàn)方式

發(fā)布時間:2020-06-27 08:59:37 來源:網(wǎng)絡(luò) 閱讀:5129 作者:cnn237111 欄目:移動開發(fā)

版權(quán)聲明: 本文由 一只博客 發(fā)表于?bloghome博客

文章鏈接:?https://www.bloghome.com.cn/user/cnn237111

常規(guī)實現(xiàn)方法:

ajax無法實現(xiàn)上傳文件,因此常規(guī)情況下,要實現(xiàn)無刷新上傳文件的做法,是在頁面隱藏一個iframe,然后將上傳form的target指向這個iframe,變相的實現(xiàn)。如下代碼:

<p?id="uploading"?>Uploading...<img?src="loading.gif"/>
<form?action="upload.php"?method="post"?enctype="multipart/form-data"?target="upload_target"?onsubmit="startUpload();"?>
????File:?<input?name="myfile"?type="file"?/>
??????????<input?type="submit"?name="submitBtn"?value="Upload"?/>
</form>
<iframe?id="upload_target"?name="upload_target"?src="#"?>
</iframe>

upload_target是一個長寬都是0的iframe,所以頁面上看不見他。還需要配合js,使得效果更好:

<script>
function?startUpload(){
???$('#uploading').show();
}
function?finisheUpload(i){
???$('#uploading').hide();
???if(i==0)
???{
?????alert("上傳成功");
????}
????else
???{
??????alert("上傳失敗");
????}
}
</script>

其中startUpload方法是在提交表單的時候觸發(fā),而由于沒有什么回調(diào)函數(shù),因此finisheUpload只能由upload.php文件的輸出控制。通常就是在輸出中輸出一段javascript代碼來執(zhí)行。

php代碼如下:

<?php
header("Content-Type:text/html;charset=utf-8");
$destination_path?=?getcwd().DIRECTORY_SEPARATOR;
$filname?=?$destination_path?.?basename(?$_FILES['myfile']['name']);
$filname=iconv("UTF-8","gb2312",$filname);
if(move_uploaded_file($_FILES['myfile']['tmp_name'],?$filname))?{
???echo?"<script?language=\"javascript\"?type=\"text/javascript\">window.parent.finisheUpload(0);</script>?";
}
else
{
???echo?"<script?language=\"javascript\"?type=\"text/javascript\">window.parent.finisheUpload(1);</script>?";
}


注意,輸出javascript的時候,由于調(diào)用的js方法是在iframe外定義的,要在iframe內(nèi)調(diào)用js方法,需要指定window.parent。

————————

HTML5下的實現(xiàn)方法:

先介紹一下FileReader對象:

FileReader對象的詳細說明可以在W3C官方文檔中查看。

該接口提供方法來讀取文件對象或者Blob對象。它繼承了EventTarget,接口的描述如下:

[Constructor]
????interface?FileReader:?EventTarget?{
??????//?async?read?methods
??????void?readAsArrayBuffer(Blob?blob);
??????void?readAsText(Blob?blob,?optional?DOMString?label);
??????void?readAsDataURL(Blob?blob);
??????void?abort();
??????//?states
??????const?unsigned?short?EMPTY?=?0;
??????const?unsigned?short?LOADING?=?1;
??????const?unsigned?short?DONE?=?2;
??????readonly?attribute?unsigned?short?readyState;
??????//?File?or?Blob?data
??????readonly?attribute?(DOMString?or?ArrayBuffer)??result;
??????readonly?attribute?DOMError??error;
??????//?event?handler?attributes
??????attribute?EventHandler???????attribute?EventHandler?onprogress;
??????attribute?EventHandler???????attribute?EventHandler?onabort;
??????attribute?EventHandler?onerror;
??????attribute?EventHandler?????};


可以看到有4個異步方法,其中3個是讀取,1個是放棄,4個狀態(tài)屬性,1個result,1個error和6個事件。(之前還有readAsBinaryString方法,不過已經(jīng)被W3C去除了)這6個事件的觸發(fā)時機如下:

loadstart --When the read starts.

progress --While reading (and decoding) blob

abort --When the read has been aborted. For instance, by invoking the abort() method.

error --When the read has failed (see errors).

load --When the read has successfully completed.

loadend --When the request has completed (either in success or failure).

下面演示一個例子,讀取一個文本文檔,并且alert出來內(nèi)容。

<script>
function?readfile(dom)
{
????var?file?=?dom.files[0];
????var?textType?=?/text.*/;//正則表達式,使之匹配text/html,text/plain
????if?(file.type.match(textType))?{
????var?reader?=?new?FileReader();
????//注冊事件函數(shù),即等讀完內(nèi)容后,要做的事情
????reader.onload?=?function(e)?{
????????alert(reader.result);
????}
????//異步讀取內(nèi)容
????reader.readAsText(file,'gb2312');
????????$("#msg").html("正在執(zhí)行異步讀取");
????}
????else?{
????????alert("文件不支持");
????}
}
</script>
<input?type="file"?id="testfiles"?name="files[]"?onchange="readfile(this);"?/>
<div?id="msg"></div>

——————————————————————————————

下面演示一個例子,讀取一個DataURL的,DataURL其實是一種DataURI(要知道URI的更多細節(jié),可以去http://css-tricks.com/data-uris/,或者維基百科了解更多)。它提供了一種在瀏覽器中顯示數(shù)據(jù)的途徑。比如你要顯示一個圖片(百度的logo)的話,你可以如下寫:

<img?src="https://cache.yisu.com/upload/information/20200302/42/7387.jpg"?/>

你也可以用它的URI去寫,如下:

<img src="data:p_w_picpath/gif;base64,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" />

src中填寫的字符串就是DataURI,格式如下:

data:[<mime type>][;charset=<charset>][;base64],<encoded data>

這種URI其實很有用的,可以減少HTTP請求,使得網(wǎng)站提速。因此獲取了URI的話就可以加載本地的圖像了。示例代碼如下:

<script>
function?loadimg(dom)
{
????var?file?=?dom.files[0];
????//正則表達式,使之匹配p_w_picpath/jpeg等
????var?p_w_picpathType?=?/p_w_picpath.*/;
????if?(file.type.match(p_w_picpathType))?{
????????var?reader?=?new?FileReader();
????????reader.onload?=?function(e)?{
????????var?img?=?new?Image();
????????img.src?=?reader.result;
????????$("#divimg").append(img);
????}
????reader.readAsDataURL(file);
????}
????else?{
????????alert("文件不支持");
????}
}
</script>
<input?type="file"?id="testfiles"?name="files[]"?onchange="loadimg(this);"?/>
<div?id="divimg"></div>


————————————————————————————————————

還有一個方法是readAsArrayBuffer,從字面就可以看出,是把文件讀取到一個數(shù)組緩沖區(qū)。

使用readAsArrayBuffer這種方法實現(xiàn)上傳文件

下面演示一個例子:

<script>
function?upload()
{
????var?file?=?$('#testfiles')[0].files[0];
????var?reader?=?new?FileReader();
????reader.onload?=?function?(rResult)?{
????????var?filename?=?file.name;
????????var?options?=?{
????????????type:?'POST',
????????????url:?'upload.php?filename='+filename,
????????????data:?reader.result,
????????????success:function(result){
????????????????alert(result.msg);
????????????},
????????????processData:?false,??//?告訴jQuery不要去處理發(fā)送的數(shù)據(jù)
????????????contentType:?false,???//?告訴jQuery不要去設(shè)置Content-Type請求頭
????????????dataType:"json"
????????};
????????$.ajax(options);
????};
????reader.readAsArrayBuffer(file);
}
</script>
<input?type="button"?value="upload"?onclick="javascript:upload();"/>

后端PHP代碼:

try{
????$filename=$_GET['filename'];
????$input?=?file_get_contents("php://input");??//這個是獲取請求的InputStream,PHP下的寫法
????file_put_contents($filename,?$input);//保存成文件。
????echo?json_encode(array("msg"=>"上傳成功"));
}
catch(Exception?$e)
{
????echo?json_encode(array("msg"=>"上傳失敗"));
}


FormData方法

FromData的官方說明在這里。利用FormData對象,你可以使用一系列的鍵值對來模擬一個完整的表單。

以下給出一個例子,允許上傳多個文件:

<script>
function?upload()
{
????var?formdata?=?new?FormData();
????$.each($('#testfiles')[0].files,?function(i,?file)?{
????formdata.append('file-'+i,?file);
????});
????var?options?=?{
????????type:?'POST',
????????url:?'upload.php',
????????data:?formdata,
????????success:function(result){
????????????alert(result.msg);
????????},
????????processData:?false,??//?告訴jQuery不要去處理發(fā)送的數(shù)據(jù)
????????contentType:?false,???//?告訴jQuery不要去設(shè)置Content-Type請求頭
????????dataType:"json"
????};
????$.ajax(options);
}
</script>
<input?type="button"?value="upload"?onclick="javascript:upload();"/>


后臺PHP代碼:

try
{
????foreach($_FILES?as?$key?=>?$value)
????{
????????//print_r?($_FILES[$key]);?echo?"<br>";
????????move_uploaded_file(?$value["tmp_name"],?$value['name']);
????}
????????echo?json_encode(array("msg"=>"上傳成功"));
}
catch(Exception?$e)
{
????echo?json_encode(array("msg"=>"上傳失敗"));
}



參考文檔:

https://developer.mozilla.org/zh-CN/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects

http://dev.w3.org/2006/webapi/FileAPI/#FileReader-interface

http://www.w3.org/TR/XMLHttpRequest2/#interface-formdata

http://blog.teamtreehouse.com/reading-files-using-the-html5-filereader-api

http://www.dotblogs.com.tw/junegoat/archive/2013/05/27/test-fileapi-multiupload-readasarraybuffer.aspx

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI