后端code
創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供平房網(wǎng)站建設(shè)、平房做網(wǎng)站、平房網(wǎng)站設(shè)計(jì)、平房網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、平房企業(yè)網(wǎng)站模板建站服務(wù),10年平房做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
?php
class Upload{
private $filepath = './upload'; //上傳目錄
private $tmpPath; //PHP文件臨時(shí)目錄
private $blobNum; //第幾個(gè)文件塊
private $totalBlobNum; //文件塊總數(shù)
private $fileName; //文件名
private $md5FileName;
public function __construct($tmpPath,$blobNum,$totalBlobNum,$fileName, $md5FileName){
$this-tmpPath = $tmpPath;
$this-blobNum = $blobNum;
$this-totalBlobNum = $totalBlobNum;
$this-fileName = $this-createName($fileName, $md5FileName);
$this-moveFile();
$this-fileMerge();
}
//代碼不支持IE 因?yàn)镮E對(duì)HTML5支持不好$("#file").change(function(event) { var file = $("#file")[0].files[0]; PostFile(file,0); });function PostFile(file,i){ var name = file.name, //文件名 size = file.size, //總大小shardSize = 2 * 1024 * 1024, shardSize = 2 * 1024 * 1024,//以2MB為一個(gè)分片 shardCount = Math.ceil(size / shardSize); //總片數(shù) if(i = shardCount){ return; } //計(jì)算每一片的起始與結(jié)束位置 var start = i * shardSize, end = Math.min(size, start + shardSize); //構(gòu)造一個(gè)表單,F(xiàn)ormData是HTML5新增的 var form = new FormData(); form.append("data", file.slice(start,end)); //slice方法用于切出文件的一部分 form.append("lastModified", file.lastModified); //slice方法用于切出文件的一部分 form.append("name", name); form.append("total", shardCount); //總片數(shù) form.append("index", i + 1); //當(dāng)前是第幾片 //Ajax提交 $.ajax({ url: "/test/AjaxFile", type: "POST", data: form, async: true, //異步 processData: false, //很重要,告訴jquery不要對(duì)form進(jìn)行處理 contentType: false, //很重要,指定為false才能形成正確的Content-Type success: function(data){ if(data){ i = data++; var num = Math.ceil(i*100 / shardCount); $("#output").text(num+'%'); PostFile(file,i); } } }); }
Html5終于解決了上傳文件的同時(shí)顯示文件上傳進(jìn)度的老問題?,F(xiàn)在大部分的網(wǎng)站用Flash去實(shí)現(xiàn)這一功能,還有一些網(wǎng)站繼續(xù)采用Html formwith enctype=multipart/form-data,但是需要修改服務(wù)器端可用才能顯示給用戶文件上傳的進(jìn)度。本質(zhì)上你需要做的工作是在服務(wù)器端接收一個(gè)文件時(shí),你發(fā)送給它一個(gè)字節(jié)流,所以你需要知道你已經(jīng)接收到多少字節(jié)并以某種方式傳達(dá)這些信息給客戶端瀏覽器,在這個(gè)過程一直在不斷的進(jìn)行文件的上傳。這種方式運(yùn)行的非常好,不像Flash上傳那這樣充滿了問題(特別是處理大文件上傳的時(shí)候),然而這種方法是相當(dāng)復(fù)雜的并且聽起來不容易理解,因?yàn)槟惚举|(zhì)上是接管了整個(gè)服務(wù)器端的處理(獲取字節(jié)流的時(shí)候)同時(shí)包括了在服務(wù)器端實(shí)現(xiàn)multipart/form-data協(xié)議,伴隨一系列的其他事情。
使用Html5 上傳文件
XMLHttpRequest 在Html5 規(guī)范中已經(jīng)有全新的變化,規(guī)定了XMLHttpRequest Level 2規(guī)范(目前最新版本)包含下列新的特性:
處理字節(jié)流,例如作為上傳或者下載的File,Blob,F(xiàn)ormData對(duì)象
上傳或者下載中的進(jìn)度事件
跨站點(diǎn)請(qǐng)求
允許創(chuàng)建匿名請(qǐng)求
可以設(shè)置請(qǐng)求超時(shí)
在這篇文章中我們將能夠更清楚的看到#1和#2兩個(gè)特性。通常,上傳文件用XMLHttpRequest并且提供上傳進(jìn)度信息給最終的用戶,需要注意的是這種方式解決了不需要服務(wù)器端做任何改變,至少是目前處理multipart/form-data協(xié)議。所以服務(wù)器端的處理邏輯保留不變,這使得開發(fā)者適應(yīng)這種技術(shù)相當(dāng)容易。
圖1:文件上傳畫面-準(zhǔn)備上傳 圖2:顯示上傳完成畫面
注意:上面的圖片中,信息提示區(qū)域是提供給用戶的:
當(dāng)前選中文件的信息
文件名
文件大小
文件類型
上傳完成多少的百分比進(jìn)度條
上傳速度或者上傳帶寬
距離上傳完成大概還有多長時(shí)間
已上傳文件大小
服務(wù)器端的響應(yīng)
上面第6項(xiàng)或許看起來不重要,但事實(shí)上是相當(dāng)重要的。因?yàn)槲覀冇肵MLHttpRequest,上傳發(fā)生在后臺(tái),頁面沒有發(fā)生跳轉(zhuǎn)等任何變化,所以對(duì)于你用它處理其他一些事情來說是一個(gè)非常好的特性。
Html5 Progress Event
對(duì)于Html5 Progress Events規(guī)范,Html5 Progess Events提供了下列與本次討論相關(guān)的信息
total - 總的字節(jié)數(shù)
loaded - 到目前為止上傳的字節(jié)數(shù)
lengthComputable - 可計(jì)算的已上傳字節(jié)
請(qǐng)注意到我們需要用兩個(gè)信息去計(jì)算要顯示給用戶的其他所有信息。要計(jì)算出來其他的信息通過上面我們得到信息是相當(dāng)容易的,但是那需要一些額外的代碼并且創(chuàng)建一個(gè)定時(shí)器。
Html5 Progress Event 應(yīng)該是什么
考慮到有一部分人想更好的提供給用戶所有的信息,所以Html5 Progress Event應(yīng)該更好的滿足需要,因?yàn)樗o瀏覽器供應(yīng)商提供這些額外信息是相當(dāng)簡單的,所以建議progress event應(yīng)該修改成如下:
total - 總的字節(jié)數(shù)
loaded - 到目前為止上傳的字節(jié)數(shù)
lengthComputable - 可計(jì)算的已上傳字節(jié)
transferSpeed long類型
timeRemaining JavaScript 日期對(duì)象
Html5 上傳 用XMLHttpRequest
瀏覽器支持情況
支持這一特性的瀏覽器最低版本
Firefox 4.0 beta 6
Chrome 6
Safari 5.02
IE 9 Beta and Opera 10.62 不支持這一特性
簡單的示例
下面是一個(gè)完整的Html頁面包含了實(shí)現(xiàn)文件上傳并帶有進(jìn)度提示的JavaScript代碼,只是實(shí)現(xiàn)了基本的功能,感興趣的可以自己做擴(kuò)展。 需要吧上傳接口修改成自己服務(wù)的。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
!DOCTYPE html
html
head
titleUpload Files using XMLHttpRequest - Minimal/title
script type="text/javascript"
function fileSelected() {
var file = document.getElementById('fileToUpload').files[0];
if (file) {
var fileSize = 0;
if (file.size 1024 * 1024)
fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
else
fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
}
}
function uploadFile() {
var fd = new FormData();
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);
xhr.open("POST", "upload.do");//修改成自己的接口
xhr.send(fd);
}
function uploadProgress(evt) {
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
}
else {
document.getElementById('progressNumber').innerHTML = 'unable to compute';
}
}
function uploadComplete(evt) {
/* 服務(wù)器端返回響應(yīng)時(shí)候觸發(fā)event事件*/
alert(evt.target.responseText);
}
function uploadFailed(evt) {
alert("There was an error attempting to upload the file.");
}
function uploadCanceled(evt) {
alert("The upload has been canceled by the user or the browser dropped the connection.");
}
/script
/head
body
form id="form1" enctype="multipart/form-data" method="post" action="Upload.aspx"
div class="row"
label for="fileToUpload"Select a File to Upload/labelbr /
input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"/
/div
div id="fileName"/div
div id="fileSize"/div
div id="fileType"/div
div class="row"
input type="button" onclick="uploadFile()" value="Upload" /
/div
div id="progressNumber"/div
/form
/body
/html
我們?cè)O(shè)計(jì)的上傳文件大約在500m左右
我第一反應(yīng)是blob,在HTML5中添加了blob類型用來定義前端較大數(shù)據(jù),之前使用過blob流傳輸視頻再使用html5中video標(biāo)簽讀取blob流,所以blob可以作為這種文件傳輸?shù)妮d體,那如何提交呢,使用可formdata提交blob數(shù)據(jù),這種方式可以承受較大數(shù)據(jù)量的文件,但在使用formdata傳輸?shù)倪^程中,瀏覽器會(huì)卡死,無法操作。
還是舍友提醒,可采用數(shù)據(jù)分割的方式,一部分一部分上傳。后經(jīng)百度得知,文件分割要防止數(shù)據(jù)丟失進(jìn)行大小校驗(yàn),以及防止外部入侵,進(jìn)行分段前端加密,后端校驗(yàn)。
百度發(fā)布了一款分割上傳的組件web upload,可包含文件分割,大小校驗(yàn)等功能。
網(wǎng)站為:
佩服我們大學(xué)宿舍的技術(shù)氛圍,出差回來的火車上跟大學(xué)舍友在微信上聊了兩三個(gè)小時(shí)的技術(shù),,,那天剛好是大學(xué)生開學(xué)那幾天,路上好多大學(xué)生,好懷念自己的大學(xué)生活,好懷念與大學(xué)舍友談天說地或技術(shù)探討到深夜的日子
說了幾個(gè)前端的問題,總結(jié)記錄一下吧
其中只有一個(gè)我會(huì)的,,,先說這個(gè)問題,其他的我學(xué)習(xí)完再分享,留坑。。。。。。
播放大視頻文件等待下載時(shí)間過長的缺陷,本身就不是HTML5的問題,服務(wù)器問題和視頻格式問題。
Flash插件播放fla的傳統(tǒng)方式上:這個(gè)現(xiàn)在YOUKU基本上FLV格式。建議在服務(wù)器上裝流媒體服務(wù),然后用HTML5點(diǎn)播地址,不要直接HTML5讀取視頻地址,沒人會(huì)這樣做除非只是非常小,非常短的的視頻文件。
相對(duì)于下載后觀看的網(wǎng)絡(luò)播放形式而言,流媒體的典型特征是把連續(xù)的音頻和視頻信息壓縮后放到網(wǎng)絡(luò)服務(wù)器上,用戶邊下載邊觀看,而不必等待整個(gè)文件下載完畢。由于流媒體技術(shù)的優(yōu)越性,該技術(shù)廣泛應(yīng)用于視頻點(diǎn)播、視頻會(huì)議、遠(yuǎn)程教育、遠(yuǎn)程醫(yī)療和在線直播系統(tǒng)中。
相關(guān)信息
sewise流媒體服務(wù)器軟件系統(tǒng)是一整套流媒體編碼、分發(fā)和存儲(chǔ)的軟件系統(tǒng),包含直播、點(diǎn)播、虛擬直播、剪切、轉(zhuǎn)碼、視頻管理系統(tǒng)。這些軟件支持多屏多系統(tǒng)播放,終端客戶使用手機(jī)、平板、電腦、電視等終端,ios、安卓、windows、linux等系統(tǒng),都能支持播放。
點(diǎn)播服務(wù)器軟件:支持mp4、flv、mov、ts、wmv、mkv、rmvb等多種類型的文件上傳;支持2種上傳方式,可上傳大文件;支持H.264/AAC編碼;強(qiáng)大的服務(wù)端實(shí)時(shí)轉(zhuǎn)碼能力,轉(zhuǎn)碼輸出3種不同碼率的視頻文件;支持web應(yīng)用播放需求及android系統(tǒng)、ios系統(tǒng)播放需求。