[关闭]
@15013890200 2018-08-29T09:33:28.000000Z 字数 4927 阅读 910

vue upload 文件上传

vue javascript 插件

文件上传功能是交互式网站必不可少的功能。一年前,笔者还是什么都不懂得小白(虽然现在懂得也很少)的时候,被这个功能折磨了好一阵子。求助师兄师姐才勉强会用封装好的插件。
最近,抽空写了个简单的文件上传插件,下面将介绍此插件的特点。

1、该插件严格上来说,并不能算真正的文件上传插件。我只是利用该插件获取到自己选择的文件的信息,包括文件对象和文件base64编码,然后返回。至于后来怎样上传、何时上传就因人而异。
2、该插件支持的配置:是否支持多选、上传文件的大致类型、上传文件的后缀、上传文件的字节大小、上传文件的宽高、是否严格限制上传文件的宽高。
3、由于该插件并不将文件直接上传到服务器。因此给用户带来撤回选择文件的功能,减轻服务器的压力。
4、选择的文件展示方面,支持图片缩略图。定制化excel、word、ppt、txt、html、pdf、rar、video文件图标,以及默认文件图标。


源代码

  1. <template>
  2. <div class="j_div_upload clearfix">
  3. <input type="file" class="j_ip_hide" @change="getSelect">
  4. <div class="j_div_imgs">
  5. <div class="j_imgs_div">
  6. <div v-for="(img,index) in imgs" class="j_div_item">
  7. <img :src="img.icon?img.icon:img.base64" class="j_img_item">
  8. <span :title="img.name">{{img.name}}</span>
  9. <i class="j_i_close" @click="deleteItem(index)"></i>
  10. </div>
  11. </div>
  12. <div class="j_div_add" @click="select"></div>
  13. </div>
  14. </div>
  15. </template>
  16. <script>
  17. import Vue from 'vue';
  18. export default{
  19. name: 'myupload',
  20. data(){
  21. return {
  22. imgs: [],//存放选中的文件对象
  23. multiple: false,//标志是否支持多文件上传
  24. type: '',//文件的大致类型。目前最好传入image或者video
  25. size: null,//允许文件的字节大小
  26. format: [],//允许文件的具体后缀
  27. width: null,//图片的宽度
  28. height: null,//图片的高度
  29. strict: false,//图片长宽是否严格限制在标注尺寸
  30. icon: require('./img/file.png')
  31. }
  32. },
  33. props: {
  34. uploadObj: {
  35. type: Object,
  36. default: null
  37. }
  38. },
  39. methods: {
  40. select: function(){
  41. /** 触发文件上传操作 */
  42. this.$el.firstChild.click();
  43. },
  44. getSelect: function(event){
  45. /** 获取文件对象并进行处理和控制 */
  46. if(!event.target.files || !event.target.files[0])return;
  47. let _this = this;
  48. let file = event.target.files[0];
  49. if(this.type && file.type.indexOf(this.type) === -1){
  50. this.Layer.alert('上传文件类型错误,应该上传 '+this.type+' 类型');
  51. return;
  52. }
  53. if(this.format && this.format.length){
  54. let file_type = file.name.split('.').pop(1).toLowerCase();
  55. if(this.format.indexOf(file_type) === -1){
  56. this.Layer.alert('上传文件后缀与指定后缀类型不符( '+this.format.join(',')+' )');
  57. return;
  58. }
  59. }
  60. if(this.size && file.size > this.size * 1024 * 1024){
  61. this.Layer.alert('文件超过'+this.size+'M限制');
  62. return;
  63. }
  64. let reader = new FileReader();
  65. reader.readAsDataURL(file);
  66. reader.onload = function(evt){
  67. if(file.type.indexOf('image') !== -1){
  68. let image = new Image();
  69. image.src = evt.target.result;
  70. image.onload = function(){
  71. let w = image.width;
  72. let h = image.height;
  73. if(_this.strict){
  74. if(_this.width && _this.height && (w != _this.width || h != _this.height)){
  75. _this.Layer.alert('图片的宽高不符合要求,宽必须为:'+_this.width+',高必须为:'+_this.height);
  76. return;
  77. }
  78. }
  79. else{
  80. if(_this.width && _this.height && (w > _this.width || h > _this.height)){
  81. _this.Layer.alert('图片的宽高不符合要求,宽不能大于:'+_this.width+',高不能大于:'+_this.height);
  82. return;
  83. }
  84. }
  85. if(_this.multiple){
  86. _this.imgs.push({
  87. name: file.name,
  88. date: file.lastModified,
  89. base64: evt.target.result,
  90. file: file
  91. });
  92. }
  93. else{
  94. _this.imgs = [{
  95. name: file.name,
  96. date: file.lastModified,
  97. base64: evt.target.result,
  98. file: file
  99. }];
  100. }
  101. }
  102. }
  103. else{
  104. let file_tail = file.type.split('.').pop();
  105. switch(file_tail){
  106. case 'sheet': _this.icon = require('./img/excel.png');break;
  107. case 'document': _this.icon = require('./img/word.png');break;
  108. case 'presentation': _this.icon = require('./img/ppt.png');break;
  109. default: _this.icon = require('./img/file.png');
  110. }
  111. if(file.type.indexOf('pdf') !== -1)_this.icon = require('./img/pdf.png');
  112. if(file.type.indexOf('video') !== -1)_this.icon = require('./img/video.png');
  113. if(file.type === 'text/plain')_this.icon = require('./img/txt.png');
  114. if(file.type === 'text/html')_this.icon = require('./img/html.png');
  115. if(!file.type && file.name.split('.').pop() == 'rar')_this.icon = require('./img/rar.png');
  116. if(_this.multiple){
  117. _this.imgs.push({
  118. name: file.name,
  119. date: file.lastModified,
  120. base64: evt.target.result,
  121. file: file,
  122. icon: _this.icon
  123. });
  124. }
  125. else{
  126. _this.imgs = [{
  127. name: file.name,
  128. date: file.lastModified,
  129. base64: evt.target.result,
  130. file: file,
  131. icon: _this.icon
  132. }];
  133. }
  134. }
  135. }
  136. setTimeout(function(){
  137. event.target.files = null;
  138. },500);
  139. },
  140. deleteItem: function(idx){
  141. /** 删除已选的文件 */
  142. this.imgs.splice(idx,1);
  143. }
  144. },
  145. beforeMount(){
  146. for(let i in this.uploadObj){
  147. if(i !== 'imgs'){
  148. this.$data[i] = this.uploadObj[i];
  149. }
  150. }
  151. console.log(this.uploadObj);
  152. },
  153. watch: {
  154. 'imgs': function(){
  155. let files = {base64: [],files: []};
  156. this.imgs.forEach(function(item){
  157. files.base64.push(item.base64);
  158. files.files.push(item.file);
  159. });
  160. this.$emit('callback',files);
  161. }
  162. }
  163. }
  164. </script>
  165. <style scoped>
  166. *{padding: 0;margin: 0;}
  167. .j_div_upload{margin-bottom:10px;}
  168. .j_ip_hide{width: 0;height: 0;opacity: 0;overflow: hidden;border:none;outline: none;margin: 0;padding: 0;}
  169. .j_div_add{width: 80px;height: 80px;background:url(img/add-pic.png) no-repeat;background-size: 80px 80px;margin: 0;float: left;cursor: pointer;}
  170. .j_imgs_div,.j_div_imgs{float:left;}
  171. .j_div_item{width:80px;height:100px;float:left;margin-right:10px;text-align:center;position:relative;}
  172. .j_img_item{width:80px;height:80px;background-color:#ddd;}
  173. .j_div_item span{color:#bbb;font-size:12px;float:left;display:inline-block;width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}
  174. .j_i_close{background:url(img/close.png) no-repeat;display:inline-block;width:16px;height:16px;position:absolute;top:-5px;right:-5px;cursor:pointer;}
  175. </style>

插件注册及引用省略


参数配置

参数名 参数意义 参数类型 默认值 是否必须
multiple 是否支持多文件上传 Boolean false 否
type 支持文件大致格式(最好传image或video) string 无 否
size 支持文件字节大小 number null 否
format 允许的文件后缀 array null 否
width 图片的宽度限制 number null 否
height 图片的高度限制 number null 否
strict 是否严格限制图片宽高 Boolean false 否

当strict参数为true时,会严格限制图片的宽高等于约定的尺寸,否则只控制图片的宽高小于约定的尺寸即可。


效果图
c92866ecc7697d9f0ae907960fdab26.png-128.3kB

4d1c26a9ae5333236451bf3f673c8b6.png-11.8kB

977a62f1d261c940f119b9eefe9e104.png-11.6kB

ec4217e09b49325832ea586dcfe1283.png-10kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注