qw110946 6 years ago
parent
commit
8f116c3769
11 changed files with 515 additions and 188 deletions
  1. 0 80
      index.html
  2. 23 98
      index.js
  3. 53 0
      js/linkMysql.js
  4. 132 0
      js/upload.js
  5. 68 0
      package-lock.json
  6. 3 1
      package.json
  7. 61 0
      src/back.html
  8. 37 0
      src/file-md5.js
  9. 97 0
      src/index.html
  10. 1 0
      src/spark-md5.min.js
  11. 40 9
      splitUpload.js

+ 0 - 80
index.html

@@ -1,80 +0,0 @@
-<html>
-<head>
-	<meta charset="UTF-8">
-	<title>Document</title>
-	<script src="http://www.1473.cn/uform.js"></script>	
-</head>
-<style>
-form p span{
-	margin-left: 20px;
-}
-</style>
-<body>
-	<form action="">
-		<input type="file" id="uploadfile" >
-		<button id="uploadbtn">开始上传</button>
-		<p>文件名<span id="filename">无</span></p>
-		<p>大小<span id="filesize">0</span></p>
-		<p>进度<span id="progress">0%</span></p>
-	</form>
-</body>
-<script src="./splitUpload.js"></script>	
-<script>
-	var els = {
-		uploadfile: $("#uploadfile")[0],
-		uploadbtn: $("#uploadbtn")[0],
-		filename: $("#filename")[0],
-		filesize: $("#filesize")[0],
-		progress: $("#progress")[0]
-	}
-	// 当前上传文件的file对象
-	var currentFile = null;
-	// 暂停的标签
-	// var stopSign = true;
-	// 开始上传事件
-	uploadbtn.onclick = function(e){
-    	e.preventDefault();
-
-		if(!currentFile)
-			return;
-
-		// 开始上传
-		beginUpload(currentFile)
-	}
-	// 选择文件事件
-	uploadfile.onchange = function(){
-		var file = uploadfile.files[0], name, size;
-
-		if(!file || !file.name)
-			return;
-
-		name = file.name;
-		size = file.size;
-
-		els.filename.innerHTML = name;
-		els.filesize.innerHTML = size > 1024
-            ? size / 1024 > 1024
-	            ? size / (1024 * 1024) > 1024
-		            ? (size / (1024 * 1024 * 1024)).toFixed(2) + 'GB'
-		            : (size / (1024 * 1024)).toFixed(2) + 'MB'
-	            : (size / 1024).toFixed(2) + 'KB'
-            : (size).toFixed(2) + 'B';
-        // 设置当前文件
-		currentFile = file;
-	}
-	/**
-	 * 开始上传
-	 * @param  {File} file  上传的文件
-	 */
-	function beginUpload(file){
-		
-        splitUpload(file, function(thunkTo, totalSize) { // success
-      		progress.innerHTML = (100*thunkTo/totalSize).toFixed(2) +'%';
-      		if(thunkTo === totalSize)
-          	progress.innerHTML += '   写入成功';
-        }, function(res) { // error
-  			progress.innerHTML += '   写入失败';
-        })
-	}
-</script>	
-</html>

+ 23 - 98
index.js

@@ -1,113 +1,38 @@
-var fs = require('fs');
 var express = require('express');
 var app = express();
 var bodyParser = require('body-parser');
-var formidable = require('formidable')
+var upload = require('./js/upload');
 
 app.use(bodyParser.json());  
-app.use(bodyParser.urlencoded({extended: false}));  
+app.use(bodyParser.urlencoded({extended: false}));
 
-// 首页
-app.get('/', function (req, res) {
-  res.sendFile(__dirname+'/index.html');
-});
+/*function generateUUID() { // Public Domain/MIT
+  var d = new Date().getTime();
+  if (typeof performance !== 'undefined' && typeof performance.now === 'function'){
+    d += performance.now(); //use high-precision timer if available
+  }
+  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+    var r = (d + Math.random() * 16) % 16 | 0;
+    d = Math.floor(d / 16);
+    return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
+  });
+}*/
 
-app.use('/file', express.static('upload'));
 
-// js
-app.get('/splitUpload.js', function (req, res) {
-  res.sendFile(__dirname+'/splitUpload.js');
+// 首页
+app.get('/', function (req, res) {
+  res.redirect('/file')
 });
+// 静态网页
+app.use('/file', express.static('src'));
+// 上传完成的文件
+app.use('/uploadFile', express.static('upload'));
+// 上传页面
+app.post('/upload', upload);
 
-// 上传页
-app.post('/upload', function (req, res) {
-	
-	var form = new formidable.IncomingForm();   //创建上传表单
-  	form.uploadDir = __dirname + '/temp';
-	// 读取formdata
-	form.parse(req, function(err, fields, files) {
-		// console.log(err);
-		// console.log(fields);
-		// console.log(files);
-		// return
-		if(err){
-   			uploadError(res, err, 501);
-			return;
-		}
-		// theFile
-		// fileName
-		// totalSize
-		// isFirstChunk 是否第一次上传
-		// isLastChunk 是否最后一次上传
-		var file = files.theFile;
-		var fileName = fields.fileName;
-		var isFirstChunk = fields.isFirstChunk;
-		var isLastChunk = fields.isLastChunk;
-		// if(isTrue(isFirstChunk)){
-		// 	fileName 
-		// }
-		var fileDir = __dirname + '/upload/' + fileName;
-	    // console.log(file.path)
-		// 开启读取模式
-		fs.readFile(file.path, {flag: 'r+'}, function (err, data) {
-		    if(err) {
-		   		uploadError(res, err, 502);
-		    }else{
-				// 是否第一次读取
-				if(isTrue(isFirstChunk)){
-					// 写入文件
-					fs.writeFile(fileDir, data, {}, function (err) {
-					   	if(err) {    	
-					   		uploadError(res, err, 503);
-					    } else {
-					    	uploadSuccess(res, isLastChunk);
-					    }
-					});
-				}else{
-					// 追加写入文件
-					fs.appendFile(fileDir, data, function (err) {
-					   	if(err) {
-					   		uploadError(res, err, 505);
-					    } else {
-					    	uploadSuccess(res, isLastChunk);
-					    }
-					});
-				}
-              	fs.unlinkSync(file.path)
-		    }
-		})
-	})
-});
 // 启动服务器
 var server = app.listen(3000, function () {
 	var host = server.address().address;
 	var port = server.address().port;
 	console.log('Listening at http://%s:%s', host, port);
-});
-// 判断字符串true
-function isTrue(t){
-	return t == 'true'|| t == true;
-}
-/**
- * 打印上传成功的log并且返回状态信息
- * @param  {[type]}  res         [response]
- * @param  {Boolean} isLastChunk [string | boolean]
- */
-function uploadSuccess(res, isLastChunk) {
-   	console.log(isTrue(isLastChunk)? '写入成功': '写入完毕');
-	res.send({
-		status:200,
-		isLastChunk: isLastChunk
-	})
-}
-/**
- * 打印错误并返回
- * @param  {[type]} res    [response]
- * @param  {[type]} err    [错误信息]
- * @param  {[type]} status [错误状态]
- */
-function uploadError(res, err, status) {
-	console.error(err);
-	console.log(status);
-	res.send({status:status})
-}
+});

+ 53 - 0
js/linkMysql.js

@@ -0,0 +1,53 @@
+var mysql = require('mysql');
+var pool = mysql.createPool({
+  host: '10.20.5.88',
+  port: '14062',
+  user: 'root',
+  password: 'usestudio-1',
+  database:'UseStudio_Upload'
+});
+
+// connection.connect();
+
+module.exports = {
+  query: function(sql,callback){
+    pool.getConnection(function(err,conn){
+      if(err){
+        console.log(err);
+        return [];
+      }else{
+        conn.query(sql,function(qerr,vals,fields){
+          //释放连接
+          conn.release();
+          //事件驱动回调
+          callback(qerr,vals,fields);
+        });
+      }
+    });
+  },
+  call: function(name, args, callback){
+    var sql = 'CALL ' + name + '('+ (args.length>0? ("'"+ args.join("','") + "'"): '') + ')';
+    pool.getConnection(function(err,conn){
+      if(err){
+        console.log(err);
+        return [];
+      }else{
+        conn.query(sql,function(qerr,vals,fields){
+          //释放连接
+          conn.release();
+          //事件驱动回调
+          callback(qerr,vals,fields);
+        });
+      }
+    });
+  },
+  end: function(){
+    // connection.end();
+  }
+};
+
+// var query=function(sql,callback){
+
+// };
+
+// module.exports=query;

+ 132 - 0
js/upload.js

@@ -0,0 +1,132 @@
+var fs = require('fs');
+var formidable = require('formidable');
+var linkMysql = require('./linkMysql');
+const uuidv1 = require('uuid/v1');
+module.exports = function (req, res) {
+
+  var form = new formidable.IncomingForm();   //创建上传表单
+  // 临时路径
+  form.uploadDir = __dirname + '/../temp';
+  // 读取formdata
+  form.parse(req, function(err, fields, files) {
+    // console.log(err);
+    // console.log(fields);
+    // console.log(files);
+    // return
+    if(err){
+      console.log('fields',fields)
+      uploadError(res, err, 501);
+      return;
+    }
+    // theFile
+    // fileName
+    // totalSize
+    // isFirstChunk 是否第一次上传
+    // isLastChunk 是否最后一次上传
+    var file = files.theFile;
+    var fileName = fields.fileName;
+    console.log('fileName',fileName)
+    var fileHash = fields.fileHash;
+    var fileChunk = fields.fileChunk;
+    var fileSize = fields.totalSize;
+    var isFirstChunk = isTrue(fields.isFirstChunk);
+    var isLastChunk = isTrue(fields.isLastChunk);
+    // 文件类型
+    var fileType =  fileName.toLowerCase().split('.').splice(-1);
+    // 服务器名
+    var fileServerName = uuidv1()+'.'+fileType;
+    // if(isFirstChunk){
+    // 	fileName
+    // }
+    // console.log(file.path)
+
+    // 查询文件是否存在
+    linkMysql.call('selectFileMsgWhereFileHash', [fileHash],function(qerr,vals,fields){
+      if(qerr){
+        uploadError(res, err, 401);
+      }else{
+        vals  = vals[0][0];
+        if(vals){//如果存在 获取文件名
+          fileServerName = vals.FileServerName
+        }
+
+        var fileDir = __dirname + '/../upload/' + fileServerName;
+        // 开启读取模式
+        fs.readFile(file.path, {flag: 'r+'}, function (err, data) {
+          if(err) {
+            uploadError(res, err, 502);
+          }else{
+            // 是否第一次读取
+            if(isFirstChunk){
+              // 写入文件
+              fs.writeFile(fileDir, data, {}, function (err) {
+                if(err) {
+                  uploadError(res, err, 503);
+                } else {
+                  // 上传成功创建文件数据
+                  linkMysql.call('addFileMsg', [fileServerName, fileName, fileType, fileHash, fileSize, (isLastChunk?'1':'0')],function(qerr,vals,fields){
+                    if(qerr){
+                      uploadError(res, err, 5031);
+                    }else{
+                      // console.log(qerr,vals,fields)
+                      uploadSuccess(res, isLastChunk, fileServerName);
+                    }
+                  })
+                }
+              });
+            }else{
+              // 追加写入文件
+              fs.appendFile(fileDir, data, function (err) {
+                if(err) {
+                  uploadError(res, err, 505);
+                } else {
+                  // 上传成功修改文件数据
+                  linkMysql.call('updateFileChunk', [fileHash, fileChunk, (isLastChunk?'1':'0')], function(qerr,vals,fields){
+                    if(qerr){
+                      console.log(qerr)
+                      uploadError(res, err, 5051);
+                    }else{
+                      // console.log(qerr,vals,fields)
+                      uploadSuccess(res, isLastChunk, fileServerName);
+                    }
+                  })
+                }
+              });
+            }
+            fs.unlinkSync(file.path) // 删除临时文件
+          }
+        })
+      }
+    })
+  })
+}
+
+// 判断字符串true
+function isTrue(t){
+  return t === 'true'|| t === true;
+}
+/**
+ * 打印上传成功的log并且返回状态信息
+ * @param  {[type]}  res         [response]
+ * @param  {Boolean} isLastChunk  是否最后一片 [string | boolean]
+ * @param  {Boolean} fileServerName 文件服务器名 [string]
+ */
+function uploadSuccess(res, isLastChunk, fileServerName) {
+  console.log(isTrue(isLastChunk)? '写入成功': '写入完毕');
+  res.send({
+    status:200,
+    isLastChunk: isLastChunk,
+    link: isLastChunk?'/uploadFile/' + fileServerName:''
+  })
+}
+/**
+ * 打印错误并返回
+ * @param  {[type]} res    [response]
+ * @param  {[type]} err    [错误信息]
+ * @param  {[type]} status [错误状态]
+ */
+function uploadError(res, err, status) {
+  console.error(err);
+  console.log(status);
+  res.send({status:status})
+}

+ 68 - 0
package-lock.json

@@ -18,6 +18,11 @@
       "resolved": "http://registry.npm.taobao.org/array-flatten/download/array-flatten-1.1.1.tgz",
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
     },
+    "bignumber.js": {
+      "version": "4.0.4",
+      "resolved": "http://registry.npm.taobao.org/bignumber.js/download/bignumber.js-4.0.4.tgz",
+      "integrity": "sha1-fED1q80tZiOre5loLufbgbEYiaQ="
+    },
     "body-parser": {
       "version": "1.18.2",
       "resolved": "http://registry.npm.taobao.org/body-parser/download/body-parser-1.18.2.tgz",
@@ -60,6 +65,11 @@
       "resolved": "http://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz",
       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
     },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+    },
     "debug": {
       "version": "2.6.9",
       "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz",
@@ -202,6 +212,11 @@
       "resolved": "http://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.6.0.tgz",
       "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs="
     },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "http://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
@@ -240,6 +255,17 @@
       "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
     },
+    "mysql": {
+      "version": "2.15.0",
+      "resolved": "http://registry.npm.taobao.org/mysql/download/mysql-2.15.0.tgz",
+      "integrity": "sha1-6haEEVY0Po8uR/yJhexBzdlXO1w=",
+      "requires": {
+        "bignumber.js": "4.0.4",
+        "readable-stream": "2.3.3",
+        "safe-buffer": "5.1.1",
+        "sqlstring": "2.3.0"
+      }
+    },
     "negotiator": {
       "version": "0.6.1",
       "resolved": "http://registry.npm.taobao.org/negotiator/download/negotiator-0.6.1.tgz",
@@ -263,6 +289,11 @@
       "resolved": "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz",
       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
     },
+    "process-nextick-args": {
+      "version": "1.0.7",
+      "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-1.0.7.tgz",
+      "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+    },
     "proxy-addr": {
       "version": "2.0.3",
       "resolved": "http://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.3.tgz",
@@ -293,6 +324,20 @@
         "unpipe": "1.0.0"
       }
     },
+    "readable-stream": {
+      "version": "2.3.3",
+      "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.3.tgz",
+      "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~1.0.6",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.0.3",
+        "util-deprecate": "~1.0.1"
+      }
+    },
     "safe-buffer": {
       "version": "5.1.1",
       "resolved": "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.1.tgz",
@@ -334,11 +379,24 @@
       "resolved": "http://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz",
       "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY="
     },
+    "sqlstring": {
+      "version": "2.3.0",
+      "resolved": "http://registry.npm.taobao.org/sqlstring/download/sqlstring-2.3.0.tgz",
+      "integrity": "sha1-UluKT9Jtb3GqYegipsr5dtMa0qg="
+    },
     "statuses": {
       "version": "1.3.1",
       "resolved": "http://registry.npm.taobao.org/statuses/download/statuses-1.3.1.tgz",
       "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
     },
+    "string_decoder": {
+      "version": "1.0.3",
+      "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz",
+      "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
     "type-is": {
       "version": "1.6.16",
       "resolved": "http://registry.npm.taobao.org/type-is/download/type-is-1.6.16.tgz",
@@ -353,11 +411,21 @@
       "resolved": "http://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz",
       "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
     },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+    },
     "utils-merge": {
       "version": "1.0.1",
       "resolved": "http://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz",
       "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
     },
+    "uuid": {
+      "version": "3.2.1",
+      "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.2.1.tgz",
+      "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ="
+    },
     "vary": {
       "version": "1.1.2",
       "resolved": "http://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz",

+ 3 - 1
package.json

@@ -11,6 +11,8 @@
   "dependencies": {
     "body-parser": "^1.18.2",
     "express": "^4.16.2",
-    "formidable": "^1.2.0"
+    "formidable": "^1.2.0",
+    "mysql": "^2.15.0",
+    "uuid": "^3.2.1"
   }
 }

+ 61 - 0
src/back.html

@@ -0,0 +1,61 @@
+<html>
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport"
+        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <style>
+    table{
+      width: 50%;
+      border-color: #eee;
+    }
+    table td, table th {
+      text-align: center;
+      padding: 10px 0;
+    }
+  </style>
+</head>
+<body>
+  <a href="index.html">上传页面>></a>
+  <table border="1" cellpadding="0" cellspacing="0">
+    <thead>
+      <tr>
+        <th>名称</th>
+        <th>大小</th>
+        <th>上传状态</th>
+        <th>操作</th>
+      </tr>
+    </thead>
+    <tbody>
+    </tbody>
+  </table>
+</body>
+<script src="http://www.1473.cn/uform.js"></script>
+<script>
+  U.A.Request('http://cd.1473.cn/php', (['db.1473.cn', 'UseStudio_Upload', "selectFileMsg"]), function (r) {
+    var data = r.value;
+    var el = $('tbody')[0];
+
+    for(var i = 0, item; i < data.length; i++) {
+      item = data[i];
+
+      // 文件大小格式化
+      item.FileSize = item.FileSize > 1024 // 文件大小
+        ? item.FileSize / 1024 > 1024
+          ? item.FileSize / (1024 * 1024) > 1024
+            ? (item.FileSize / (1024 * 1024 * 1024)).toFixed(2) + 'GB'
+            : (item.FileSize / (1024 * 1024)).toFixed(2) + 'MB'
+          : (item.FileSize / 1024).toFixed(2) + 'KB'
+        : (item.FileSize).toFixed(2) + 'B';
+
+      el.innerHTML += "<tr>\
+          <td>"+ item.FileName +"</td>\
+          <td>"+ item.FileSize +"</td>\
+          <td>"+ (item.Finish === '1'? '完成': '未完成') +"</td>\
+          <td><a href='/uploadFile/"+ item.FileServerName +"' download='"+ item.FileName +"'>下载</a></td>\
+        </tr>\
+      ";
+    }
+  })
+</script>
+</html>

+ 37 - 0
src/file-md5.js

@@ -0,0 +1,37 @@
+function fileMd5(file, callback) {
+  var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
+    // file = this.files[0],
+    chunkSize = 2097152,                             // Read in chunks of 2MB
+    chunks = Math.ceil(file.size / chunkSize),
+    currentChunk = 0,
+    spark = new SparkMD5.ArrayBuffer(),
+    fileReader = new FileReader();
+
+  fileReader.onload = function (e) {
+    // console.log('read chunk nr', currentChunk + 1, 'of', chunks);
+    spark.append(e.target.result);                   // Append array buffer
+    currentChunk++;
+
+    if (currentChunk < chunks) {
+      loadNext();
+      callback(+(100 * currentChunk / chunks).toFixed(2)) // 参数:进度
+    } else {
+      // console.log('finished loading');
+      // console.info('computed hash', spark.end());  // Compute hash
+      callback(100, true, spark.end()) // 参数:进度、 是否完成、 文件hash
+    }
+  };
+
+  fileReader.onerror = function () {
+    console.warn('oops, something went wrong.');
+  };
+
+  function loadNext() {
+    var start = currentChunk * chunkSize,
+      end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
+
+    fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
+  }
+
+  loadNext();
+}

+ 97 - 0
src/index.html

@@ -0,0 +1,97 @@
+<html>
+<head>
+	<meta charset="UTF-8">
+	<title>Document</title>
+</head>
+<style>
+form p span{
+	margin-left: 20px;
+}
+</style>
+<body>
+	<form action="">
+		<input type="file" class="uploadfile" >
+		<button class="uploadbtn">开始上传</button>
+		<p>文件名<span class="filename">无</span></p>
+		<p>大小<span class="filesize">0</span></p>
+		<p>解析进度<span class="progress_jx">0%</span></p>
+		<p>上传进度<span class="progress">0%</span></p>
+	</form>
+	<a href="back.html">后台>></a>
+</body>
+<script src="http://www.1473.cn/uform.js"></script>
+<script src="/file/spark-md5.min.js"></script>
+<script src="/file/file-md5.js"></script>
+<script src="/file/split-upload.js"></script>
+<script>
+	var ELS = {
+		uploadfile: $(".uploadfile")[0],
+		uploadbtn: $(".uploadbtn")[0],
+		filename: $(".filename")[0],
+		filesize: $(".filesize")[0],
+      	progress_jx: $(".progress_jx")[0],
+		progress: $(".progress")[0]
+	}
+	// 当前上传文件的file对象
+	var CURRENT_FILE = null;
+	// 暂停的标签
+	// var stopSign = true;
+	// 开始上传按钮的点击事件
+    ELS.uploadbtn.onclick = function(e){
+    	e.preventDefault();
+
+		if(!CURRENT_FILE)
+			return;
+
+		// 开始上传
+		beginUpload(CURRENT_FILE)
+	}
+	// 选择文件事件
+    ELS.uploadfile.onchange = function(){
+		var file = ELS.uploadfile.files[0], name, size;
+
+		if(!file || !file.name)
+			return;
+
+		name = file.name;
+		size = file.size;
+
+		ELS.filename.innerHTML = name; // 文件名
+		ELS.filesize.innerHTML = size > 1024 // 文件大小
+            ? size / 1024 > 1024
+	            ? size / (1024 * 1024) > 1024
+		            ? (size / (1024 * 1024 * 1024)).toFixed(2) + 'GB'
+		            : (size / (1024 * 1024)).toFixed(2) + 'MB'
+	            : (size / 1024).toFixed(2) + 'KB'
+            : (size).toFixed(2) + 'B';
+
+		// 设置当前文件
+		CURRENT_FILE = file;
+	}
+	/**
+	 * 开始上传
+	 * @param  {File} file  上传的文件
+	 */
+	function beginUpload(file){
+
+      fileMd5(file, function(progress, finish, fileHash) {
+
+        ELS.progress_jx.innerHTML = progress +'%'; // 解析进度条
+
+        if(finish) {
+          ELS.progress_jx.innerHTML += '解析完成';
+
+          // 上传
+          splitUpload(file, fileHash, function(thunkTo, totalSize, link) { // success
+            ELS.progress.innerHTML = (100 * thunkTo / totalSize).toFixed(2) +'%';
+            console.log(link)
+            if(thunkTo === totalSize)
+              ELS.progress.innerHTML += '   写入成功';
+          }, function(res) { // error
+            ELS.progress.innerHTML += '   写入失败';
+          })
+		}
+	  })
+	}
+</script>	
+</html>

File diff suppressed because it is too large
+ 1 - 0
src/spark-md5.min.js


+ 40 - 9
splitUpload.js

@@ -14,15 +14,18 @@
 	 * @param  {[type]} count       [上传的次数] 
 	 * @param  {[type]} counts       [上传的总次数]
      * @param  {[string]} uploadLink  [上传链接]  默认
+     * @param  {[type]} fileHash    [文件Hash]
 	 */
-    function loop(file, totalSize, eachSize, SucCallback, ErrCallback, count, counts, uploadLink){
+    function loop(file, totalSize, eachSize, SucCallback, ErrCallback, count, counts, fileHash, uploadLink){
     	var thunkFrom = count *	eachSize;// 切割起始端
     	var thunkTo = (count + 1) * eachSize > totalSize ? totalSize : (count + 1) * eachSize;// 切割末端
 
 		fd = new FormData();
 		fd.append('theFile', file.slice(thunkFrom, thunkTo)); // 分好段的文件
 		fd.append('fileName', file.name); // 文件名
+      	fd.append('fileHash', fileHash); // 文件名
 		fd.append('totalSize', totalSize); // 大小
+     	fd.append('fileChunk', count); // 大小
 		fd.append('isFirstChunk', count === 0); // 是否第一次上传
 		fd.append('isLastChunk', count === counts - 1); // 是否最后一次上传
 
@@ -34,13 +37,13 @@
           	if(xhr.readyState==4 && xhr.status==200){
 	          	var rs = JSON.parse(xhr.responseText);
 	          	if(rs.status == 200){
-	          		SucCallback(thunkTo, totalSize)
+	          		SucCallback(thunkTo, totalSize, rs.link)
 	          		// isLastChunk
 	          		if(count === counts - 1){
 	          			return;
 	          		}
 	          		// 继续上传
-					loop(file, totalSize, eachSize, SucCallback, ErrCallback, ++count, counts, uploadLink)
+					loop(file, totalSize, eachSize, SucCallback, ErrCallback, ++count, counts, fileHash, uploadLink)
 	          	}else{
           			ErrCallback(rs)
 	          	}
@@ -48,20 +51,48 @@
 		};
 		xhr.send(fd);
     }
+
+  /**
+   * 文件是否存在
+   * @param hash hash
+   * @param callback 回调
+   */
+    function fileIsExists(hash, callback) {
+      U.A.Request('http://cd.1473.cn/php', (['db.1473.cn', 'UseStudio_Upload', "selectFileMsgWhereFileHash", hash]), function (r) {
+        if(r.value[0]){
+          callback(r.value[0])
+		}else{
+          callback(false)
+		}
+      })
+	}
     /**
      * 分割上传
      * @param  {[type]} file        [文件Flie对象]
+     * @param  {[type]} fileHash    [文件Hash]
      * @param  {[function]} SucCallback [成功回调]
      * @param  {[function]} ErrCallback [失败回调]
      * @param  {[string]} uploadLink  [上传链接] default 
      */
-	return function(file, SucCallback, ErrCallback, uploadLink) {
-		uploadLink = uploadLink || '/upload';
-        var totalSize = file.size; // 总大小
-        var eachSize = 1024 * 1000; // 每次上传大小  这里是100kb
-        var counts = Math.ceil(totalSize / eachSize); // 上传的总次数
+	return function(file, fileHash, SucCallback, ErrCallback, uploadLink) {
+      uploadLink = uploadLink || '/upload';
+      var totalSize = file.size; // 总大小
+      var eachSize = 1024 * 100; // 每次上传大小  这里是100kb
+      var counts = Math.ceil(totalSize / eachSize); // 上传的总次数
 
-		loop(file, totalSize, eachSize, SucCallback, ErrCallback, 0, counts, uploadLink)
+      fileIsExists(fileHash, function(data){
+      	if(data === false){
+          loop(file, totalSize, eachSize, SucCallback, ErrCallback, 0, counts, fileHash, uploadLink)
+		} else {
+      		if(data.Finish == '1'){
+              SucCallback(totalSize, totalSize)
+			}else{
+              // 存在的文件,获取上次上的分片数目,继续上传
+              loop(file, totalSize, eachSize, SucCallback, ErrCallback, ~~data.Chunk+1, counts, fileHash, uploadLink)
+			}
+		}
+	  })
+    }
 	//test
 	/*size > 1024
             ? size / 1024 > 1024