`
ilovejsj
  • 浏览: 205589 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

基于Http的多线程上传

阅读更多

来自:http://www.iteye.com/topic/452368?page=1

大米盘基于google的gears
Array.prototype.remove = function(b) {
	for ( var a = 0; a < this.length; a++) {
		if (b == this[a]) {
			this.splice(a, 1)
		}
	}
};
function Map() {
	this.keys = [];
	this.index = 0;
	this.data = {};
	this.length = 0;
	this.set = function(a, b) {
		if ("undefined" === typeof this.data[a]) {
			this.keys.push(a);
			this.length = this.keys.length
		}
		this.data[a] = b
	};
	this.get = function(a) {
		if ("undefined" === typeof this.data[a]) {
			return null
		}
		return this.data[a]
	};
	this.del = function(a) {
		if ("undefined" !== typeof this.data[a]) {
			this.keys.remove(a);
			delete this.data[a];
			this.length--
		}
	};
	this.sum = function(a) {
		var d = 0;
		for ( var c = 0; c < this.keys.length; c++) {
			var b = this.keys[c];
			if ("undefined" !== typeof a) {
				d += this.data[b][a]
			} else {
				d += this.data[b]
			}
		}
		return d
	};
	this.foreach = function(c) {
		if ("function" !== typeof c) {
			return
		}
		for ( var b = 0; b < this.keys.length; b++) {
			var a = this.keys[b];
			var d = c(a, this.data[a], b, this);
			if ("break" === d) {
				break
			}
		}
	};
	this.each = function() {
		var a = this.current();
		if (false !== a) {
			this.index++
		}
		return a
	};
	this.current = function() {
		if (this.index >= this.length) {
			return false
		}
		var a = this.data[this.keys[this.index]];
		return a
	};
	this.reset = function() {
		this.index = 0
	};
	this.toString = function() {
		var c = "Object Map {\n";
		for ( var b = 0; b < this.keys.length; b++) {
			var a = this.keys[b];
			c += "    " + a + ":" + this.data[a] + ",\n"
		}
		c += "}";
		return c
	}
}
function DmpGearsUpload(handlers) {
	this.text_has_not_selected = "请选择要上传的文件!";
	this.text_file_to_large = "您所选的文件太大,单个文件请不要超过%s!";
	this.maxChunks = 2000;
	this.minChunks = 3;
	this.progressFrequency = 1000;
	this.checkTimeout = 5000;
	this.chunkSize = 8388608;
	this.maxFileSize = 5368709120;
	this.maxThreads = 5;
	this.workerUrl = "http://vdami/js/worker.js";
	this.tablesVersion = 903231727;
	this.maxProcess = 1;
	this.multiFileSupport = 0;
	this.geoAddress = null;
	this.locationLoaded = false;
	this.files = new Map;
	this.checkoutLock = false;
	this.runningProcess = new Map;
	this.crossFuncs = new Map;
	this.wp = google.gears.factory.create("beta.workerpool");
	this.cwp = false;
	this.uploadStarted = false;
	this.showOpenFile = function() {
	};
	this.showSubmit = function() {
	};
	this.showProgress = function() {
	};
	this.showComplete = function() {
	};
	this.showInit = function() {
	};
	this.showInitError = function() {
	};
	this.showInitFail = function() {
	};
	this.showNetError = function() {
	};
	var _private_allow_handlers = {};
	if ("undefined" !== typeof handlers) {
		for (n in handlers) {
			console.debug("bind handler: " + n);
			this[n] = handlers[n]
		}
	}
	this.openFile = function() {
		var this_ = this;
		var desktop = google.gears.factory.create("beta.desktop");
		var singleFile = !this.multiFileSupport;
		desktop
				.openFiles(
						function(files) {
							if (1 > files.length) {
								return
							}
							if (singleFile) {
								this_.files = new Map
							}
							while (file = files.pop()) {
								var fileid = Math.random();
								if (this_.maxFileSize < file.blob.length) {
									alert(this_.text_file_to_large.replace(
											"%s",
											genFileSize(this_.maxFileSize)));
									return
								}
								if (1073741824 < file.blob.length
										&& file.name.match(/\.(rar|zip|7z)$/)) {
									alert("温馨提示:如果您上传的RAR是为了打包多个视频文件,我们建议您还是分开上传。因为每个视频文件极有可能在电驴和迅雷的P2P网络里已经有很多源,单独下载时会大大增加下载速度。")
								}
								this_.files.set(fileid, {
									fileid : fileid,
									name : file.name,
									hash : "",
									size : file.blob.length,
									blob : file.blob,
									loaded : 0,
									cmaps : [],
									threads : new Map,
									status : "init"
								});
								var tmp_chunks = Math.ceil(file.blob.length
										/ this_.chunkSize);
								var chunk_size = this_.chunkSize;
								if (tmp_chunks > this_.maxChunks) {
									chunk_size = Math.ceil(file.blob.length
											/ this_.maxChunks)
								} else {
									if (tmp_chunks < this_.minChunks) {
										chunk_size = Math.ceil(file.blob.length
												/ this_.minChunks)
									}
								}
								console.debug("chunksize front:"
										+ this_.chunkSize + " final:"
										+ chunk_size);
								console.debug("chunks front:"
										+ tmp_chunks
										+ " final:"
										+ Math.ceil(file.blob.length
												/ chunk_size));
								var chunk_size = 9728000;
								var i = 0;
								var w = true;
								do {
									var start = i * chunk_size;
									var chunk_no = start / chunk_size;
									if ((start + chunk_size) >= file.blob.length) {
										offset = file.blob.length - start;
										w = false
									} else {
										offset = chunk_size
									}
									this_.files.get(fileid).cmaps[i] = {
										no : i,
										start : start,
										offset : offset,
										status : "init"
									};
									i++
								} while (w);
								this_.showOpenFile(file);
								console.debug(file)
							}
						}, {
							singleFile : singleFile
						})
	};
			this.upload = function() {
				if (0 === this.files.length) {
					alert(this.text_has_not_selected);
					return false
				}
				var ps = this.files.length > this.maxProcess ? this.maxProcess
						: this.files.length;
				for ( var i = 0; i < ps; i++) {
					console.debug("require process " + i);
					this.showSubmit(this.newProcess())
				}
				this.uploadStarted = true
			},
			this.newProcess = function() {
				if (this.maxProcess < this.runningProcess.length) {
					console.debug("new process needless.");
					return
				}
				var this_ = this;
				this.files
						.foreach( function(key, val, i, files) {
							if ("" == val.hash) {
								console.debug("start new process. " + val.name);
								try {
									clearInterval(this_.runningProcess
											.get(val.fileid))
								} catch (e) {
								}
								this_.runningProcess.set(val.fileid,
										setInterval( function() {
											this_.checkProcess(val.fileid)
										}, this_.progressFrequency));
								val.status = "uploading";
								var threads = val.cmaps.length > this_.maxThreads ? this_.maxThreads
										: val.cmaps.length;
								for ( var i = 0; i < threads; i++) {
									this_.newThread(val)
								}
								return "break"
							} else {
								console.debug("new process skip. " + val.name
										+ "/" + i + "/" + val.hash)
							}
						})
			};
	this.setThreads = function(threads) {
		var file = this.files.current();
		this.maxThreads = threads;
		if (0 == file.threads.length) {
			return
		}
		var neednew = this.maxThreads - file.threads.length;
		if (neednew > 0) {
			for ( var i = 0; i < neednew; i++, this.newThread(file)) {
			}
		}
	}, this.newThread = function(file) {
		if (this.maxThreads <= file.threads.length) {
			console.debug("new thread needless.");
			return
		}
		for ( var i = 0; i < file.cmaps.length; i++) {
			var cmap = file.cmaps[i];
			if ("init" == cmap.status || "error" == cmap.status) {
				console.debug(cmap);
				cmap.status = "uploading";
				var range = cmap.start + "-" + cmap.offset;
				var req = {
					method : "POST",
					url : "/?app=dami_upload&act=chunk&todo=upload&pid="
							+ file.fileid + "&total_size=" + file.size,
					headers : [ [ "Content-Type", "application/octet-stream" ],
							[ "Content-Range", "bytes " + range ] ],
					blob : file.blob.slice(cmap.start, cmap.offset)
				};
				var this_ = this;
				var funcs = {
					onprogress : function(obj) {
						obj.cmapno = cmap.no;
						obj.fileid = file.fileid;
						this_.onProgress(obj);
						file.threads.set(obj.cmapno, {
							reqid : reqid,
							loaded : obj.loaded
						})
					},
					oncomplete : function(obj) {
						obj.cmapno = cmap.no;
						obj.fileid = file.fileid;
						console.debug("funcs_fileid:" + obj.fileid);
						this_.onComplete(obj);
						file.threads.del(cmap.no)
					}
				};
				this.fileid = file.fileid;
				var reqid = this.crossPost(req, funcs);
				file.threads.set(cmap.no, {
					reqid : reqid,
					loaded : 0
				});
				console.debug("new thread reqid: " + reqid);
				break
			}
		}
	};
	this.onProgress = function(obj) {
		var file = this.files.get(obj.fileid);
		var cmap = file.cmaps[obj.cmapno]
	}, this.checkProcess = function(fileid) {
		var file = this.files.get(fileid);
		var loaded = file.loaded + file.threads.sum("loaded");
		var speed = genSpeed( {
			size : file.size,
			received : loaded
		});
		if (0 == parseInt(speed.speed)) {
			if ("undefined" === typeof this._checkProcessTimeout) {
				var this_ = this;
				this._checkProcessTimeout = setTimeout( function() {
					this_.showNetError( {
						fileid : fileid
					})
				}, this.checkTimeout)
			}
		} else {
			try {
				clearTimeout(this._checkProcessTimeout);
				delete this._checkProcessTimeout
			} catch (e) {
			}
			this.showProgress( {
				fileid : file.fileid,
				total : file.size,
				loaded : loaded,
				speed : speed.speed,
				timeLeft : speed.timeLeft,
				running : file.threads.length
			})
		}
	};
	this.onComplete = function(obj) {
		console.debug(obj.responseText);
		var file = this.files.get(obj.fileid);
		var cmap = file.cmaps[obj.cmapno];
		do {
			if (200 != obj.status) {
				console.debug(obj.status);
				cmap.status = "error";
				file.threads.del(obj.cmapno);
				this_.showNetError( {
					fileid : file.fileid
				});
				break
			}
			var data = false;
			try {
				data = eval("(" + obj.responseText + ")")
			} catch (e) {
			}
			if (false === data) {
				break
			}
			if (0 < parseInt(data.error) && this_.onError(data)) {
				console.debug("chunk upload error.");
				file.threads.del(obj.cmapno);
				break
			}
			cmap.status = "complete";
			file.loaded += cmap.offset;
			file.threads.del(obj.cmapno)
		} while (false);
		if (file.size > file.loaded) {
			console.debug("new upload thread.");
			return this.newThread(file)
		}
		this.showProgress( {
			fileid : file.fileid,
			total : file.size,
			loaded : file.size,
			speed : 0,
			timeLeft : "...",
			running : 1
		});
		this.checkout(obj)
	};
	this.checkout = function(obj) {
		try {
			clearTimeout(this.runningProcess.get(obj.fileid))
		} catch (e) {
		}
		if (this.checkoutLock) {
			return
		}
		this.checkoutLock = true;
		var file = this.files.get(obj.fileid);
		var cmap = file.cmaps[obj.cmapno];
		var url = "/?app=dami_upload&act=chunk&todo=checkout&pid="
				+ file.fileid + "&total_size=" + file.size + "&merge_thread=1";
		var filename = encodeURIComponent(file.name);
		var req_timeout = (Math.ceil(file.size / 11534336) + 10) * 1000;
		var req = {
			timeout : req_timeout,
			method : "POST",
			url : url,
			headers : [ [ "Content-Disposition",
					'attachment; filename="' + filename + '"' ] ]
		};
		var this_ = this;
		try {
			clearTimeout(this._checkProcessTimeout);
			delete this._checkProcessTimeout
		} catch (e) {
		}
		var funcs = {
			oncomplete : function(req_obj) {
				if (200 != req_obj.status) {
					this_.checkoutLock = false;
					console.debug(req_obj);
					console.debug("retry checkout.");
					return this_.checkout(obj)
				}
				var data = eval("(" + req_obj.responseText + ")");
				if (0 < parseInt(data.error) && this_.onError(data)) {
					return
				}
				this_.cleanup(obj);
				console.debug("chekcout");
				setTimeout( function() {
					console.debug("chekcout");
					var file = this_.files.get(obj.fileid);
					file.hash = data.fileinfo.filehash;
					file.status = "complete";
					console.debug("<---------------");
					console.debug(file);
					console.debug(this_.files);
					console.debug("--------------->");
					this_.runningProcess.del(obj.fileid);
					data.fileid = obj.fileid;
					this_.showComplete(data);
					this_.checkoutLock = false
				}, 1000)
			}
		};
		this.crossPost(req, funcs)
	};
	this.cleanup = function(obj) {
		var file = this.files.get(obj.fileid);
		var url = "/?app=dami_upload&act=chunk&todo=cleanup&pid=" + file.fileid
				+ "&total_size=" + file.size;
		var req = {
			method : "POST",
			url : url
		};
		console.debug(url);
		var funcs = {};
		this.crossPost(req, funcs)
	};
	this.onError = function(obj) {
		alert("出现严重错误,上传不能继续,请稍后重试。#" + obj.error);
		window.location.href = window.location.href;
		return true
	};
	this.initRetries = 1;
	this.initCrossWorker = function() {
		if (!this.cwp) {
			if (10 < this.initRetries) {
				this.showInitFail();
				return
			}
			this.initRetries++;
			this.cwp = this.wp.createWorkerFromUrl(this.workerUrl + "?"
					+ Math.random())
		}
		console.debug("cross worker, try to initialize");
		this.showInit()
	};
	var this_ = this;
	window.onerror = function(message, url, line) {
		if (0 == line && message.match(/worker\.js/)) {
			this_.showInitError(message);
			console.debug("initialize fail");
			setTimeout( function() {
				this_.cwp = false;
				this_.initCrossWorker()
			}, 1000);
			return true
		}
		console.debug(message);
		return false
	};
	this.initCrossWorker();
	this.wp.onmessage = function(a, b, message) {
		var obj = message.body;
		var funcs = this_.crossFuncs.get(obj.reqid);
		if ("debug" === obj.act) {
			console.debug("worker:" + obj.data);
			return
		}
		if (null === funcs) {
			console.debug("nofuncs " + message.body);
			return
		}
		switch (obj.act) {
		case "onprogress":
			if ("undefined" !== typeof funcs.onprogress) {
				funcs.onprogress(obj.data)
			}
			break;
		case "oncomplete":
			if ("undefined" !== typeof funcs.oncomplete) {
				funcs.oncomplete(obj.data)
			}
			break;
		default:
			console.debug(obj);
			break
		}
	};
	this.crossPost = function(req, funcs) {
		var reqid = Math.random();
		this.crossFuncs.set(reqid, funcs);
		req.reqid = reqid;
		this.wp.sendMessage(req, this.cwp);
		this.reqid = reqid;
		return reqid
	};
	this.crossAbort = function(reqid) {
		var req = {
			abort : reqid
		};
		this.wp.sendMessage(req, this.cwp);
		this.crossFuncs.del(reqid)
	};
	this.cancel = function(fileid) {
		var file = this.files.get(fileid);
		try {
			clearInterval(this.runningProcess.get(fileid))
		} catch (e) {
		}
		var this_ = this;
		file.threads.foreach( function(key, val, i) {
			console.debug("abort:" + val.reqid);
			this_.crossAbort(val.reqid);
			file.threads.del(key)
		});
		this.files.del(fileid);
		this.runningProcess.del(fileid);
		if (this.files.length > 0 && this.uploadStarted) {
			this.upload()
		}
	}
}
function genSpeed(e) {
	var h = 300;
	if ("undefined" === typeof g_dmp_upload_lastime) {
		g_dmp_upload_lastime = new Date().getTime() - 1;
		g_dmp_upload_lastreceived = 0;
		g_dmp_upload_speed = [];
		g_dmp_cache_speed = {
			speed : 0,
			timeLeft : "Infinity"
		}
	}
	var a = g_dmp_upload_speed;
	var c = g_dmp_upload_lastime;
	var f = g_dmp_upload_lastreceived;
	var k = new Date().getTime();
	var j = k - c;
	var g;
	var b = 0;
	if (j < 1000) {
		return g_dmp_cache_speed
	}
	var l = Math.abs(parseInt((((e.received - f) / (j)) * 1000) * 1.1));
	a.push(l);
	if (h < a.length) {
		a.shift()
	}
	for ( var d = 0; d < a.length; d++) {
		b += a[d]
	}
	b = b / a.length;
	g = (0 === b) ? "Infinity" : sec2time((e.size - e.received) / b);
	g_dmp_upload_lastime = k;
	g_dmp_upload_lastreceived = e.received;
	g_dmp_cache_speed = {
		speed : genFileSize(b),
		timeLeft : g
	};
	return g_dmp_cache_speed
};
分享到:
评论

相关推荐

    基于Android的多线程上传与下载源码

    本资源提供的是基于Android的多线程上传与下载的源码,可以帮助开发者深入理解并实践这一技术。 1. **多线程下载** - **JavaSE实现**: 文件`5.多线程下载javaSe`可能包含了一个使用Java标准库实现的多线程下载示例...

    .net webservice多线程上传 cs+bs

    在" .NET WebService 多线程上传 CS+BS "这个场景中,我们主要讨论的是如何利用C#(Client-side,CS)客户端通过多线程技术与B/S(Browser/Server)架构的Web服务交互,实现大文件或大量文件的高效上传。 一、Web...

    基于WCF多线程的SOCKET文件传输服务

    **基于WCF多线程的SOCKET文件传输服务** 在软件开发中,文件传输是一个常见的需求,尤其是在分布式系统和网络应用程序中。WCF(Windows Communication Foundation)是微软提供的一种全面的面向服务的架构,用于构建...

    居于H5的多文件、大文件、多线程上传解决方案.docx

    ### 居于H5的多文件、大文件、多线程上传解决方案 #### 一、需求分析 在现代Web开发中,文件上传是一项常见的功能需求。对于需要支持多文件、大文件以及多线程上传的应用而言,传统的上传方式往往无法满足高效、...

    多线程断点续传(基于HTTP协议).zip_http 断点上传_http 断点续传_多线程断点续传_断点上传_断点续传

    本项目“多线程断点续传(基于HTTP协议)”就是这样一个解决方案,它利用HTTP协议实现了断点续传功能,并通过多线程技术提升了上传效率。 首先,我们要理解什么是断点续传。断点续传是一种文件传输机制,允许用户在...

    基于Java多线程与线程安全实践-基于Http协议的断点续传

    本实践教程将探讨如何在Java中利用多线程实现基于HTTP协议的断点续传功能,这是一个在网络传输大文件时非常有用的技术。 首先,让我们深入了解Java中的多线程。Java提供了内置的多线程支持,允许程序在同一时间执行...

    WHUT-java多线程实验-第三周-文件上传和下载.zip

    在“WHUT-java多线程实验-第三周-文件上传和下载.zip”这个实验中,我们将重点探讨如何在多线程环境中实现文件的上传和下载功能。这个实验基于IntelliJ IDEA开发环境,它是一个流行的Java集成开发环境,提供了丰富的...

    Java多线程与线程安全实践-基于Http协议的断点续传

    在本项目“Java多线程与线程安全实践-基于Http协议的断点续传”中,我们将深入探讨如何利用Java的多线程机制实现HTTP协议下的断点续传功能,这对于大文件下载或上传的场景尤为实用。 断点续传是一种允许用户在中断...

    基于SOCKET的多线程下载工具的开发

    ### 基于SOCKET的多线程下载工具的开发 #### 1. 引言 随着互联网技术的发展,文件下载已成为人们获取信息的重要手段之一。对于大文件而言,单线程下载方式往往效率低下,尤其是在网络不稳定或带宽有限的情况下。...

    基于tesseract的多线程OCR服务器的JAVA实现

    【标题】基于tesseract的多线程OCR服务器的JAVA实现 在信息技术领域,光学字符识别(OCR)技术被广泛应用于将图像中的文本转换为可编辑的电子格式。Tesseract是一款开源OCR引擎,由Google维护,它具有高精度和强大...

    基于Qt的多线程下载工具

    【基于Qt的多线程下载工具】是一种利用Qt框架实现的高效文件下载程序,它集成了多种下载协议,包括常见的HTTP、FTP以及流行的P2P技术BT(BitTorrent)。这样的设计使得用户能够灵活地从互联网上获取不同类型的资源,...

    用C#实现HTTP协议下的多线程文件传输.doc

    对于文件传输,多线程可以让我们分块并发地下载或上传文件,显著提升传输速度。 实现多线程HTTP文件传输的步骤如下: 1. **创建HTTP客户端**:使用HttpClient或WebClient实例,设置必要的请求头,如User-Agent、...

    delphi7多线程上传.7z

    在这个特定的场景中,"delphi7多线程上传.7z"是一个压缩包文件,其中包含了使用Delphi 7开发的多线程上传功能的相关代码和资源。多线程技术在现代软件开发中扮演着重要角色,特别是在处理大型文件上传或下载时,它...

    VC 6.0 基于HTTP的多线程下载程序源码.rar

    《VC 6.0基于HTTP的多线程下载程序源码解析》 在软件开发领域,尤其是网络编程中,多线程技术与HTTP协议的应用至关重要。这篇解析将深入探讨一个用VC 6.0编写的,基于HTTP协议的多线程下载程序源码,旨在帮助初学者...

    Java多线程与线程安全实践-基于Http协议的断点续传.zip

    # Java多线程与线程安全实践-基于Http协议的断点续传.zip中文介绍 这个压缩文件包含了一个Java多线程与线程安全实践的项目,它是基于Http协议的断点续传实现。 在这个项目中,我们将学习如何使用Java多线程技术来...

    http ftp 多线程下载

    本文将深入探讨如何实现“http ftp 多线程下载”这一技术,并基于提供的描述,我们将详细解析一个完整的实例。 首先,HTTP(超文本传输协议)是互联网上应用最广泛的一种网络协议,用于从万维网服务器传输超文本到...

    WEBAPI多线程并发测试工具

    **标题与描述解析** ...以上是基于给定信息生成的API测试和多线程并发测试相关的详细知识点,涵盖了从理论基础到实践操作的多个层面。对于开发和维护高质量的Web API服务,这些知识都是必不可少的。

    用C#语言实现http协议下的多线程文件传输

    ### 使用C#实现HTTP协议下的多线程文件传输 在当今高速发展的互联网世界里,文件传输的速度直接影响着用户体验和工作效率。传统的单线程文件下载方式往往受到网络带宽和服务器响应时间的限制,效率较低。然而,随着...

    VC++ FTP、HTTP 多线程断点续传下载文件源码.rar

    该压缩包文件“VC++ FTP、HTTP 多线程断点续传下载文件源码.rar”包含了一套基于VC++实现的源代码,用于通过FTP和HTTP协议进行多线程断点续传下载文件。这一技术在现代软件开发中非常重要,尤其是在处理大文件或网络...

Global site tag (gtag.js) - Google Analytics