1 http://www.resumablejs.com/ 官网
2 upload.html
3 <!DOCTYPE html>
4 <html lang="en">
5
6 <div>
7 <a href="#" id="browseButton" >Select files</a>
8 <div>
9 <div>
10 <input id="btnCancel" type="button" onClick='r.pause()'value="Cancel All Uploads"
11 style="margin-left: 2px; height: 22px; font-size: 8pt;" />
12 <br />
13 </div>
14 <script src="resumable.js"></script>
15 <script>
16 var r = new Resumable({
17 target:'upload.php',
18 chunkSize:2*1024*1024,
19 simultaneousUploads:4,
20 testChunks:true,
21 throttleProgressCallbacks:1,
22
23 });
24
25 r.assignBrowse(document.getElementById('browseButton'));
26
27 r.on('fileSuccess', function(file){
28 // console.debug(file);
29 });
30 r.on('fileProgress', function(file){
31 // console.debug(file);
32 });
33 r.on('fileAdded', function(file, event){
34 r.upload();
35 //console.debug(file, event);
36 });
37 r.on('fileRetry', function(file){
38 //console.debug(file);
39 });
40 r.on('fileError', function(file, message){
41 //console.debug(file, message);
42 });
43 r.on('uploadStart', function(){
44 //console.debug();
45 });
46 r.on('complete', function(){
47 //console.debug();
48 });
49 r.on('progress', function(){
50 //console.debug();
51 });
52 r.on('error', function(message, file){
53 //console.debug(message, file);
54 });
55 r.on('pause', function(file,message){
56 //console.debug();
57
58 });
59 r.on('cancel', function(){
60 //console.debug();
61 });
62 </script>
63
64 </html>
65
66 upload.php
67 <?php
68 /**
69 * This is the implementation of the server side part of
70 * Resumable.js client script, which sends/uploads files
71 * to a server in several chunks.
72 *
73 * The script receives the files in a standard way as if
74 * the files were uploaded using standard HTML form (multipart).
75 *
76 * This PHP script stores all the chunks of a file in a temporary
77 * directory (`temp`) with the extension `_part<#ChunkN>`. Once all
78 * the parts have been uploaded, a final destination file is
79 * being created from all the stored parts (appending one by one).
80 *
81 * @author Gregory Chris (http://online-php.com)
82 * @email www.online.php@gmail.com
83 */
84
85
86 ////////////////////////////////////////////////////////////////////
87 // THE FUNCTIONS
88 ////////////////////////////////////////////////////////////////////
89
90 /**
91 *
92 * Logging operation - to a file (upload_log.txt) and to the stdout
93 * @param string $str - the logging string
94 */
95 function _log($str) {
96
97 // log to the output
98 $log_str = date('d.m.Y').": {$str}\r\n";
99 echo $log_str;
100
101 // log to file
102 if (($fp = fopen('upload_log.txt', 'a+')) !== false) {
103 fputs($fp, $log_str);
104 fclose($fp);
105 }
106 }
107
108 /**
109 *
110 * Delete a directory RECURSIVELY
111 * @param string $dir - directory path
112 * @link http://php.net/manual/en/function.rmdir.php
113 */
114 function rrmdir($dir) {
115 if (is_dir($dir)) {
116 $objects = scandir($dir);
117 foreach ($objects as $object) {
118 if ($object != "." && $object != "..") {
119 if (filetype($dir . "/" . $object) == "dir") {
120 rrmdir($dir . "/" . $object);
121 } else {
122 unlink($dir . "/" . $object);
123 }
124 }
125 }
126 reset($objects);
127 rmdir($dir);
128 }
129 }
130
131 /**
132 *
133 * Check if all the parts exist, and
134 * gather all the parts of the file together
135 * @param string $dir - the temporary directory holding all the parts of the file
136 * @param string $fileName - the original file name
137 * @param string $chunkSize - each chunk size (in bytes)
138 * @param string $totalSize - original file size (in bytes)
139 */
140 function createFileFromChunks($temp_dir, $fileName, $chunkSize, $totalSize) {
141
142 // count all the parts of this file
143 $total_files = 0;
144 foreach(scandir($temp_dir) as $file) {
145 if (stripos($file, $fileName) !== false) {
146 $total_files++;
147 }
148 }
149
150 // check that all the parts are present
151 // the size of the last part is between chunkSize and 2*$chunkSize
152 if ($total_files * $chunkSize >= ($totalSize - $chunkSize + 1)) {
153
154 // create the final destination file
155 if (($fp = fopen('temp/'.$fileName, 'w')) !== false) {
156 for ($i=1; $i<=$total_files; $i++) {
157 fwrite($fp, file_get_contents($temp_dir.'/'.$fileName.'.part'.$i));
158 _log('writing chunk '.$i);
159 }
160 fclose($fp);
161 } else {
162 _log('cannot create the destination file');
163 return false;
164 }
165
166 // rename the temporary directory (to avoid access from other
167 // concurrent chunks uploads) and than delete it
168 if (rename($temp_dir, $temp_dir.'_UNUSED')) {
169 rrmdir($temp_dir.'_UNUSED');
170 } else {
171 rrmdir($temp_dir);
172 }
173 }
174
175 }
176
177
178 ////////////////////////////////////////////////////////////////////
179 // THE SCRIPT
180 ////////////////////////////////////////////////////////////////////
181
182 //check if request is GET and the requested chunk exists or not. this makes testChunks work
183 if ($_SERVER['REQUEST_METHOD'] === 'GET') {
184
185 $temp_dir = 'temp/'.$_GET['resumableIdentifier'];
186 $chunk_file = $temp_dir.'/'.$_GET['resumableFilename'].'.part'.$_GET['resumableChunkNumber'];
187 if (file_exists($chunk_file)) {
188 header("HTTP/1.0 200 Ok");
189 } else
190 {
191 header("HTTP/1.0 404 Not Found");
192 }
193 }
194
195
196
197 // loop through files and move the chunks to a temporarily created directory
198 if (!empty($_FILES)) foreach ($_FILES as $file) {
199
200 // check the error status
201 if ($file['error'] != 0) {
202 _log('error '.$file['error'].' in file '.$_POST['resumableFilename']);
203 continue;
204 }
205
206 // init the destination file (format <filename.ext>.part<#chunk>
207 // the file is stored in a temporary directory
208 $temp_dir = 'temp/'.$_POST['resumableIdentifier'];
209 $dest_file = $temp_dir.'/'.$_POST['resumableFilename'].'.part'.$_POST['resumableChunkNumber'];
210
211 // create the temporary directory
212 if (!is_dir($temp_dir)) {
213 mkdir($temp_dir, 0777, true);
214 }
215
216 // move the temporary file
217 if (!move_uploaded_file($file['tmp_name'], $dest_file)) {
218 _log('Error saving (move_uploaded_file) chunk '.$_POST['resumableChunkNumber'].' for file '.$_POST['resumableFilename']);
219 } else {
220
221 // check if all the parts present, and create the final destination file
222 createFileFromChunks($temp_dir, $_POST['resumableFilename'],
223 $_POST['resumableChunkSize'], $_POST['resumableTotalSize']);
224 }
225 }