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

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

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