上传

180 阅读3分钟

同步上传

application/x-www-form-urlencode将post传入的数据键值对化

比如:

<input type="text" name="username" />
<input type="password" name="password" />

转换之后:

username=123&password=3553

所以form标签会有一个提交格式enctype,默认是x-www-form-urlencode。文件提交的时候传输的值的文件名(字符串,传的不是文件)。

<form action="server/upload.php" method="post" enctype="application/x-www-form-urlencode">
	<input type="text" name="file" /><br />
	<input type="file" name="file" /><br />
	<input type="submit" value="上传" />
</form>

但是文件是不能以文本的形式上传的,唯一能让文件在互联网上传输的方式就是二进制的方式:(同步上传)

enctype="multipart/form-data"

要上传多张图片,就设置multiple即可,同时注意name要加上数组符号,让后台知道是多个的形式

<input type="file" name="file[]" multiple="multiple" />

异步上传

FormData()表单数据构造函数,大多数标签都是可以通过js构造函数实例出来的,包括form标签。

我们把form标签去掉,它就不再是表单了,而是一堆输入类型控件,提交按钮也就不再具备默认提交跳转的功能了

<input type="text" id="username" />
<input type="password" id="password" />
<input type="submit" id="submitBtn" value="提交">
oSubmitBtn.onclick = function(){
	fd.append('Username', oUsername.value);
	fd.append('Password', oPassword.value);

	console.log(fd);
	console.log('username:' + fd.get('Username'));
	console.log('password:' + fd.get('Password'));
	
	fd.set('Username', 'jackson');
	
	console.log(fd.has('Password'));

	fd.delete('Password');
	console.log('password:' + fd.get('Password')); //null
}

打印出来fd是只有一个原型的空实例化对象,可以实现键值对的增删改查。

上传文件的控件还有一个files属性,可以获取到文件信息

<input type="file" id="file" multiple="" />
<input type="submit" id="submitBtn" value="上传" />
<ul class="progress-wrap"></ul>
oFile.onchange = function() {
	console.log(oFile.files);
}

sizes是字节单位,1兆/1MB = 1024 * 1024B = 1048576B

上传AJAX值的时候,会有一个upload.onprogress事件处理函数,处理上传进度的问题。

e.loaded是已下载的量,e.total是总量

步骤分析:

  1. 用files属性获取文件个数、文件名称、文件大小,用以限制传入图片的个数、大小、判断是否符合图片格式。
  2. 将错误信息添加到oProgressBar中,没有就生成进度条
  3. 用FormData()创建表单,将通过for循环获取的一个个文件添加到表单中
  4. 将表单进行AJAX异步上传,其中还要设置处理进度条的事件处理函数o.upload.onprogress,获取当前的进度条,将上传进度转换为宽度进行设置
		var oFile = document.getElementById('file'),
			oSubmitBtn = document.getElementById('submitBtn'),
			oProgressWrap = document.getElementsByClassName('progress-wrap')[0];
			fd = new FormData();

		oFile.onchange = function(){
		    var files = oFile.files,
		        fileLen = files.length;
			
			if (fileLen <= 0) {
				console.log('您还没有选择图片');
				return;
			}
			if (fileLen > 5) {
				console.log('最多可同时上传5张图片');
				return;
			}

			oProgressWrap.innerHTML = '';

			var fileName = '',
				fileSize = 0,
				maxSize = 104857600,
				fd = null,
				errorInfo = '';

			for (var i = 0; i < fileLen; i++) {
				fileName = files[i].name;
				fileSize = files[i].size;

				if (!/\.(gif|jpg|jpeg|png)$/.test(fileName)) {
					errorInfo = '『' + fileName + '』文件不是图片类型';
				}

				if (fileSize > maxSize) {
					errorInfo = '『' + fileName + '』文件超过可上传大小';
				}

				var oProgressBar = document.createElement('li');
				oProgressBar.className = 'progress-bar';
				oProgressWrap.appendChild(oProgressBar);

				if (errorInfo !== '') {
					oProgressBar.innerHTML = '<span class="error-info">' + errorInfo + '</span>';
				}else{
					oProgressBar.innerHTML = '<div class="progress"></div>';

					fd = new FormData();
					// file是后端会告诉我们的变量名
					fd.append('file', files[i]);

					var o = window.XMLHttpRequest ?
					 	    new window.XMLHttpRequest() :
					 	    new ActiveXObject('Microsoft.XMLHTTP');
					o.open('post', 'server/m_upload.php');
					
					// 有闭包问题
					(function(i){
						o.upload.onprogress = function(e){
							var e = e || window.event,
								percent = e.loaded / e.total * 100 + '%',
								thisProgressBar = oProgressWrap.getElementsByClassName('progress-bar')[i];
								
							thisProgressBar.getElementsByClassName('progress')[0].style.width = percent;
							console.log(percent)
						}
					})(i);
					
					o.send(fd);
				}
			}
		}