同步上传

文件与数据的关系

数据 是 字符串
文件 是 文件

当使用 form 表单 POST 提交时数据时,是以 applicantion/x-www-form-urlencoded 的数据编码格式来提交,把提交的数据键值对化。这是 form 使用 POST 提交时默认的方式。

  1. <input type="text" name="username" />
  2. <input type="password" name="password" />
  3. 转为 username=123&password=13579 这样的键值对格式

所以针对文件上传,要修改 form 表单的 enctype 编码方式。
对于文件会使用到 二进制blob 的方式进行编码。

  1. <form action="server/upload.php" enctype="multipart/form-data">
  2. <input type="file" name="file" />
  3. </form>

multipart/form-data 会把上传的文件转为二进制。

支持多文件

input 标签增加 multiple 属性,并且 name 改为数组(加增 []

  1. <form action="server/upload.php" enctype="multipart/form-data">
  2. <input type="file" name="file[]" multiple />
  3. </form>

如果不使用 multiple 属性,也可以使用多个 input 进行选择,并使他们的 name 为相同的数组

  1. <form action="server/upload.php" enctype="multipart/form-data">
  2. <input type="file" name="file[]" />
  3. <input type="file" name="file[]" />
  4. <input type="file" name="file[]" />
  5. <input type="file" name="file[]" />
  6. <input type="file" name="file[]" />
  7. </form>

FormData

https://www.yuque.com/sylaryip/gpvww7/vkm8fc#CfRJk
FormData() 表单数据的构造函数

  1. <input type="text" id="username" value="zhangsan"/>
  2. <input type="text" id="password" value="123" />
  3. <input type="sumbit" id="submitBtn" value="提交" />
  1. var oUsername = document.getElementById('username'),
  2. oPassword = document.getElementById('password'),
  3. oSubmitBtn = document.getElementById('submitBtn'),
  4. fd = new FormData();
  5. oSubmitBtn.onclick = function(){
  6. fd.append('Username', oUsername.value);
  7. fd.append("Password", oPassword.value);
  8. console.log(fd); // FormData {}
  9. console.log('username', fd.get('Username')); // username zhangsan
  10. console.log('password', fd.get('Password')); // password 123
  11. fd.set('username', 'lisi');
  12. fd.has('password');
  13. fd.delete('pasword');
  14. console.log('password', fd.get('Password')); // password null
  15. }

异步上传

进度条

点击查看【codepen】

选择后即刻上传

借助 input 的 onchange 事件

  1. oFile.onchange = function(){
  2. console.log(oFile.files);
  3. /*
  4. [{
  5. lastModified,
  6. lastModifiedDate,
  7. name,
  8. size, Byte
  9. type
  10. }]
  11. */
  12. var files = oFile.files,
  13. filelen = files.length;
  14. if(filelen <= 0){
  15. console.log('还未选择文件');
  16. }
  17. if(filelen > 5){
  18. console.log('最多同时上传 5 个文件');
  19. }
  20. }

文件验证

  1. oFile.onchange = function(){
  2. var files = oFile.files,
  3. filelen = files.length,
  4. fileName = '',
  5. fileSize = 0,
  6. maxSize = '1048576', // 1 Mb
  7. fd = null,
  8. errorInfo = '';
  9. for(var i = 0; i < fileLen; i ++){
  10. fileName = files[i].name;
  11. fileSize = files[i].szie;
  12. if(!/\.(gif|jpg|jpeg|png|pdf)$/.test(fileName)){
  13. errorInfo = `${fileName} 文件类型不支持`;
  14. }
  15. if(fileSize > maxSize){
  16. errorInfo = `${fileName} 超过可上传大小`;
  17. }
  18. }
  19. }

上传和进度条回调

基于 FormData 与 XHR 实现

  1. fd = new FormData();
  2. fd.append('file', files[i]);
  3. var o = window.XMLHttpRequest ?
  4. new window.XMLHttpRequest() :
  5. new ActiveXObject("Mircosoft.XMLHTTP");
  6. o.open('post', 'server/upload.php');
  7. o.upload.onprogress = function(e){
  8. var e = e || window.event,
  9. percent = e.loaded/ e.total * 100 + "%";
  10. }
  11. o.send(fd);