php+resumablejs實(shí)現(xiàn)的分塊上傳 斷點(diǎn)續(xù)傳功能示例
本文實(shí)例講述了php+resumablejs實(shí)現(xiàn)的分塊上傳 斷點(diǎn)續(xù)傳功能。分享給大家供大家參考,具體如下:
resumablejs官網(wǎng) http://www.resumablejs.com/
本站下載地址。
upload.html
<!DOCTYPE html> <html lang="en"> <div> <a href="#" rel="external nofollow" id="browseButton" >Select files</a> <div> <div> <input id="btnCancel" type="button" onClick='r.pause()'value="Cancel All Uploads" style="margin-left: 2px; height: 22px; font-size: 8pt;" /> <br /> </div> <script src="resumable.js"></script> <script> var r = new Resumable({ target:'upload.php', chunkSize:2*1024*1024, simultaneousUploads:4, testChunks:true, throttleProgressCallbacks:1, }); r.assignBrowse(document.getElementById('browseButton')); r.on('fileSuccess', function(file){ // console.debug(file); }); r.on('fileProgress', function(file){ // console.debug(file); }); r.on('fileAdded', function(file, event){ r.upload(); //console.debug(file, event); }); r.on('fileRetry', function(file){ //console.debug(file); }); r.on('fileError', function(file, message){ //console.debug(file, message); }); r.on('uploadStart', function(){ //console.debug(); }); r.on('complete', function(){ //console.debug(); }); r.on('progress', function(){ //console.debug(); }); r.on('error', function(message, file){ //console.debug(message, file); }); r.on('pause', function(file,message){ //console.debug(); }); r.on('cancel', function(){ //console.debug(); }); </script> </html>
upload.php
<?php /** * This is the implementation of the server side part of * Resumable.js client script, which sends/uploads files * to a server in several chunks. * * The script receives the files in a standard way as if * the files were uploaded using standard HTML form (multipart). * * This PHP script stores all the chunks of a file in a temporary * directory (`temp`) with the extension `_part<#ChunkN>`. Once all * the parts have been uploaded, a final destination file is * being created from all the stored parts (appending one by one). * * @author Gregory Chris (http://online-php.com) * @email www.online.php@gmail.com */ //////////////////////////////////////////////////////////////////// // THE FUNCTIONS //////////////////////////////////////////////////////////////////// /** * * Logging operation - to a file (upload_log.txt) and to the stdout * @param string $str - the logging string */ function _log($str) { // log to the output $log_str = date('d.m.Y').": {$str}\r\n"; echo $log_str; // log to file if (($fp = fopen('upload_log.txt', 'a+')) !== false) { fputs($fp, $log_str); fclose($fp); } } /** * * Delete a directory RECURSIVELY * @param string $dir - directory path * @link http://php.net/manual/en/function.rmdir.php */ function rrmdir($dir) { if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (filetype($dir . "/" . $object) == "dir") { rrmdir($dir . "/" . $object); } else { unlink($dir . "/" . $object); } } } reset($objects); rmdir($dir); } } /** * * Check if all the parts exist, and * gather all the parts of the file together * @param string $dir - the temporary directory holding all the parts of the file * @param string $fileName - the original file name * @param string $chunkSize - each chunk size (in bytes) * @param string $totalSize - original file size (in bytes) */ function createFileFromChunks($temp_dir, $fileName, $chunkSize, $totalSize) { // count all the parts of this file $total_files = 0; foreach(scandir($temp_dir) as $file) { if (stripos($file, $fileName) !== false) { $total_files++; } } // check that all the parts are present // the size of the last part is between chunkSize and 2*$chunkSize if ($total_files * $chunkSize >= ($totalSize - $chunkSize + 1)) { // create the final destination file if (($fp = fopen('temp/'.$fileName, 'w')) !== false) { for ($i=1; $i<=$total_files; $i++) { fwrite($fp, file_get_contents($temp_dir.'/'.$fileName.'.part'.$i)); _log('writing chunk '.$i); } fclose($fp); } else { _log('cannot create the destination file'); return false; } // rename the temporary directory (to avoid access from other // concurrent chunks uploads) and than delete it if (rename($temp_dir, $temp_dir.'_UNUSED')) { rrmdir($temp_dir.'_UNUSED'); } else { rrmdir($temp_dir); } } } //////////////////////////////////////////////////////////////////// // THE SCRIPT //////////////////////////////////////////////////////////////////// //check if request is GET and the requested chunk exists or not. this makes testChunks work if ($_SERVER['REQUEST_METHOD'] === 'GET') { $temp_dir = 'temp/'.$_GET['resumableIdentifier']; $chunk_file = $temp_dir.'/'.$_GET['resumableFilename'].'.part'.$_GET['resumableChunkNumber']; if (file_exists($chunk_file)) { header("HTTP/1.0 200 Ok"); } else { header("HTTP/1.0 404 Not Found"); } } // loop through files and move the chunks to a temporarily created directory if (!empty($_FILES)) foreach ($_FILES as $file) { // check the error status if ($file['error'] != 0) { _log('error '.$file['error'].' in file '.$_POST['resumableFilename']); continue; } // init the destination file (format <filename.ext>.part<#chunk> // the file is stored in a temporary directory $temp_dir = 'temp/'.$_POST['resumableIdentifier']; $dest_file = $temp_dir.'/'.$_POST['resumableFilename'].'.part'.$_POST['resumableChunkNumber']; // create the temporary directory if (!is_dir($temp_dir)) { mkdir($temp_dir, 0777, true); } // move the temporary file if (!move_uploaded_file($file['tmp_name'], $dest_file)) { _log('Error saving (move_uploaded_file) chunk '.$_POST['resumableChunkNumber'].' for file '.$_POST['resumableFilename']); } else { // check if all the parts present, and create the final destination file createFileFromChunks($temp_dir, $_POST['resumableFilename'], $_POST['resumableChunkSize'], $_POST['resumableTotalSize']); } }
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php文件操作總結(jié)》、《PHP網(wǎng)絡(luò)編程技巧總結(jié)》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫操作入門教程》及《php常見數(shù)據(jù)庫操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
相關(guān)文章
DW中鏈接mysql數(shù)據(jù)庫時(shí),建立字符集中文出現(xiàn)亂碼的解決方法
DW中鏈接mysql數(shù)據(jù)庫時(shí),建立字符集中文出現(xiàn)亂碼“????”2010-03-03IP攻擊升級(jí),程序改進(jìn)以對(duì)付新的攻擊
我上一篇文章《最新開發(fā)的網(wǎng)站防IP攻擊代碼,超級(jí)有用》寫了一個(gè)完整的防止網(wǎng)絡(luò)惡意IP攻擊的方案,使用了一個(gè)月,效果良好。2010-11-11php 不使用js實(shí)現(xiàn)頁面跳轉(zhuǎn)
頁面跳轉(zhuǎn)大多情況下是使用js,其實(shí)也可以不用,下面為大家介紹下具體的實(shí)現(xiàn),需要的朋友可以參考下2014-02-02PHP替換Word中變量并導(dǎo)出PDF圖片的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于PHP替換Word中變量并導(dǎo)出PDF圖片的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11PHP 5.3新特性命名空間規(guī)則解析及高級(jí)功能
本文介紹了PHP命名空間的一些術(shù)語,其解析規(guī)則,以及一些高級(jí)功能的應(yīng)用,希望能夠幫助讀者在項(xiàng)目中真正使用命名空間。2010-03-03PHP面向?qū)ο蟪绦蛟O(shè)計(jì)內(nèi)置標(biāo)準(zhǔn)類,普通數(shù)據(jù)類型轉(zhuǎn)為對(duì)象類型示例
這篇文章主要介紹了PHP面向?qū)ο蟪绦蛟O(shè)計(jì)內(nèi)置標(biāo)準(zhǔn)類,普通數(shù)據(jù)類型轉(zhuǎn)為對(duì)象類型,結(jié)合實(shí)例形式分析了php面向?qū)ο蟪绦蛟O(shè)計(jì)中的內(nèi)置標(biāo)準(zhǔn)類,普通數(shù)據(jù)類型概念、功能及對(duì)象類型轉(zhuǎn)換相關(guān)操作技巧,需要的朋友可以參考下2019-06-06php 從指定數(shù)字中獲取隨機(jī)組合的簡單方法(推薦)
下面小編就為大家?guī)硪黄猵hp 從指定數(shù)字中獲取隨機(jī)組合的簡單方法(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04