当前位置:   article > 正文

vue3+vite+WebUploader文件上传_vue webuploader

vue webuploader

如果你不是被迫使用WebUploader的,可以离开这篇文章去找其他适合vue3的文件上传框架了,如果你已经进了这个坑,下面的介绍希望能让你少踩点坑。

1. 安装

安装webuploader :npm install webuploader --save

webuploader依赖jq,安装jquery(我这里指定了jq的版本,没什么特别的原因...):npm install jquery@3.5.1

2. vite构建的项目注意

vite构建的项目不支持非严格模式,需要修改node_modules\webuploader\dist\webuploader.js和webuploader.fis.js 文件(改完需要删掉node_modules里面的.vite,然后重新运行):

  1. 原来:
  2. // input.on( 'change', function( e ) {
  3. // var fn = arguments.callee,
  4. // clone;
  5. // me.files = e.target.files;
  6. // // reset input
  7. // clone = this.cloneNode( true );
  8. // clone.value = null;
  9. // this.parentNode.replaceChild( clone, this );
  10. // input.off();
  11. // input = $( clone ).on( 'change', fn )
  12. // .on( 'mouseenter mouseleave', mouseHandler );
  13. // owner.trigger('change');
  14. // });
  15. 改为:
  16. var changeFn = (function even(that, e){
  17. var clone;
  18. me.files = e.target.files;
  19. // reset input
  20. clone = that.cloneNode( true );
  21. clone.value = null;
  22. that.parentNode.replaceChild( clone, that );
  23. input.off();
  24. input = $(clone).on('change', function(e){
  25. even(this, e);
  26. }).on('mouseenter mouseleave', mouseHandler);
  27. owner.trigger('change');
  28. });
  29. input.on('change', function(e){
  30. changeFn(this, e);
  31. });

3. 创建WebUploader.vue组件

注意下面的message.xx是已经被二次封装的Elmessage消息提示

  1. <template>
  2.   <div class="WebUploader">
  3.     <!-- 选择文件按钮 -->
  4.     <div class="UploadFile__chooseFile">{{butTextC}}</div>
  5.   </div>
  6. </template>
  7. <script setup>
  8. import { ref, onMounted, nextTick} from 'vue'
  9. import { message } from '@/assets/util.js'
  10. import { getVerify } from '@/service/api'
  11. // 导入webuploader
  12. import webUploader from 'webuploader'
  13. const props = defineProps({
  14. butTextC: {
  15. type: String,
  16. default: '选择文件'
  17. }
  18. })
  19. const emit = defineEmits([
  20. 'butClickC' // 用于告诉父组件点击了按钮
  21. ])
  22. // 避免webUploader.Uploader.register重复注册
  23. webUploader.Uploader.unRegister('UploadFileRegister')
  24. register()
  25. //监听分块上传过程中的三个时间点(开启分片上传时有效,我只用到了beforeSendFile,所以没有后面两块的代码), 需要在webUploader.create之前调用
  26. function register() {
  27. webUploader.Uploader.register(
  28. {
  29. 'name': 'UploadFileRegister',
  30. 'before-send-file': 'beforeSendFile',
  31. 'before-send': 'beforeSend',
  32. 'after-send-file': 'afterSendFile'
  33. },
  34. {
  35. // 时间点1::所有分块进行上传之前调用此函数
  36. beforeSendFile: function (file) {
  37. // 利用md5File()方法计算文件的唯一标记符
  38. // 创建一个deffered
  39. let deferred = webUploader.Deferred()
  40. // 1.md5File:计算文件的唯一标记,把文件名文件大小和md5拼接作为文件唯一标识,避免重复上传
  41. new webUploader.Uploader()
  42. .md5File(file, 0, 10 * 1024 * 1024)
  43. .progress(function (percentage) {})
  44. .then(function (val) {
  45. file.fileMd5 = val
  46. // 允许自定义file.xx插入文件的对象里,可以在下文的fileQueued等阶段的file中取到
  47. // file.test = xx
  48. // 如果文件后缀是禁止上传的后缀,跳过上传
  49. // 这是由于我没有找到webUploader过滤上传后缀的属性,所以在这里处理,excludeFile内容为[doc,docx]这种
  50. let flagForbid = 1
  51. store.excludeFile.forEach(item => {
  52. if(item === file.ext) {
  53. flagForbid = 2
  54. deferred.reject()
  55. message.warning(`不允许上传.${file.ext}后缀的文件!`)
  56. }
  57. })
  58. if(flagForbid === 2) return
  59. // 2.请求后台是否保存过该文件,如果存在,则跳过该文件,实现秒传功能,resolve:继续上传;reject:跳过文件,这里getVerify是本项目校验文件的一个接口,如果你们不需要校验文件是否后台有重复,可以不用这块
  60. getVerify(data)
  61. .then((res) => {
  62. if (res.success) {
  63. deferred.resolve()
  64. } else {
  65. message.error(data.name + res.message)
  66. // 文件校验失败
  67. deferred.reject()
  68. }
  69. })
  70. .catch(() => {
  71. message.error('文件校验失败')
  72. // 验证接口报错,跳过该文件
  73. deferred.reject()
  74. })
  75. })
  76. //返回deffered
  77. return deferred.promise()
  78. }
  79. }
  80. )
  81. }
  82. // 将fileType处理成.doc,.docx,(给前面多加一个.)
  83. function buildFileType(fileType) {
  84. let ts = fileType
  85. let ty = ''
  86. for (let i = 0; i < ts.length; i++) {
  87. ty = ty + '.' + ts[i] + ','
  88. }
  89. return ty.substring(0, ty.length - 1)
  90. }
  91. onMounted(() => {
  92. // webUploader.create要在页面渲染完成后进行,不然会找不到.UploadFile__chooseFile,创建不了按钮
  93. nextTick(() => {
  94. uploader = webUploader.create({
  95. auto: false,
  96. resize: false, // 不压缩image
  97. duplicate: true, // 文件去重,默认开启,不允许用户选择同一个文件
  98. server: apiUrl + 'xx/xx', // 默认文件接收服务端地址
  99. pick: {
  100. id: '.UploadFile__chooseFile', // 指定选择文件的按钮容器,不指定则不创建按钮。它不仅支持id, 也支持class、dom节点(这个没有试过)。
  101. multiple: true // 开启文件多选
  102. },
  103. accept: [
  104. {
  105. title: 'file',
  106. extensions: store.includeFile[0] ? store.includeFile : '*', // 上传接受的文件类型,'*'表示所有都接受,extensions接受的参数为:[doc,docx,pdf,xls]这种形式
  107. mimeTypes: store.includeFile[0] ? buildFileType(store.includeFile) : '*', // 指上传窗口默认展示的匹配文件后缀的文件(就是弹出的上传窗口,它可能存在很多类型的文件,如果你只写了.doc,那么此时只会显示.doc的文件,其他过滤掉不显示):参数为'.doc,.docx,.pdf,.xls'这种形式
  108. }
  109. ],
  110. fileNumLimit: 10, // 验证文件总数量, 超出则不允许加入队列,默认值:undefined,如果不配置,则不限制数量
  111. fileSizeLimit: 100 * 1024 * 1024 * 1024, // 1kb=1024*1024,验证文件总大小是否超出限制, 超出则不允许加入队列
  112. fileSingleSizeLimit: 100 * 1024 * 1024 * 1024, // 验证单个文件大小是否超出限制, 超出则不允许加入队列。
  113. chunked: true, // 是否开启分片上传
  114. chunkSize: 100 * 1024 * 1024 * 1024, // 如果要分片,每一片的文件大小,分片需要后端配合,我的项目没有,但是我又需要beforeSendFile阶段,所有我开启了分片上传,然后给每个分片为接受的文件的最大值,它就不会被真的分片了
  115. prepareNextFile: false // 在上传当前文件时,准备好下一个文件,设置成false,不然开启文件多选浏览器会卡死
  116. })
  117. // 文件加入队列后
  118. uploader.on('fileQueued', function (file) {
  119. // 文件上传
  120. uploader.upload()
  121. // 文件加入队列告诉父组件关闭弹窗
  122. emit('butClickC', 1)
  123. // 这个属性可以移除当前的文件上传,你可以自行判断什么情况下移除,注意文件加入队列是一个一个加入的,即每加入一个都有自己的uploader.on('fileQueued')方法,当前的fileQueued只能处理当前文件
  124. // uploader.removeFile(file, true)
  125. })
  126. // 上传之前
  127. uploader.on('uploadBeforeSend', function (block, data, headers) {
  128. // 注意,加入队列的文件(fileQueued)不一定都被上传了(可以在beforeSendFile时间点跳过),但uploadBeforeSend阶段的都是允许上传的文件
  129. // 允许自定义block.file.xx插入文件的对象里,可以在下文的后续阶段的file中取到
  130. // beforeSendFile时间点定义的file.test = xx,在这里可以用block.file.test取到
  131. // block.file.testA = 'xx'
  132. })
  133. // 文件上传中
  134. uploader.on('uploadProgress', function (file, percentage) {
  135. // 可以根据此时的percentage显示进度条
  136. })
  137. // 文件上传成功
  138. uploader.on('uploadSuccess', function (file, response) {
  139. message.success(file.name + '文件上传成功')
  140. })
  141. // 文件上传失败
  142. uploader.on('uploadError', function (file, reason) {
  143. message.warning(file.name + '文件上传失败')
  144. })
  145. // 文件上传错误
  146. uploader.on('error', function (handler) {
  147. if (handler == 'F_EXCEED_SIZE') {
  148. message.warning('文件上传过大!')
  149. } else if (handler == 'Q_EXCEED_SIZE_LIMIT') {
  150. message.warning('文件大小超过限制!')
  151. } else if (handler == 'Q_TYPE_DENIED') {
  152. message.warning('不允许上传此类文件!')
  153. }
  154. })
  155. // 所有文件上传完成,无论成功或者失败
  156. uploader.on('uploadFinished',function(){
  157. });
  158. })
  159. })
  160. </script>
  161. <style lang="scss">
  162. // webuploader 初始化样式,注意不能写在scope里面
  163. .webuploader-container {
  164. position: relative;
  165. }
  166. .webuploader-element-invisible {
  167. position: absolute !important;
  168. clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  169. clip: rect(1px, 1px, 1px, 1px);
  170. }
  171. .webuploader-pick {
  172. // margin-left: 0.12rem;
  173. // position: relative;
  174. display: block;
  175. cursor: pointer;
  176. background: var(--el-color-primary);
  177. // padding: 0.06rem 0.15rem;
  178. color: #fff;
  179. text-align: center;
  180. border-radius: 0.04rem;
  181. overflow: hidden;
  182. width: 1rem;
  183. height: 0.31rem;
  184. line-height: 0.31rem;
  185. border: none;
  186. }
  187. .webuploader-pick-hover {
  188. background: var(--el-color-primary-light-3);
  189. }
  190. .webuploader-pick-disable {
  191. opacity: 0.6;
  192. pointer-events: none;
  193. }
  194. </style>

4. 使用WebUploader.vue组件
  1. <template>
  2. <div class="UploadFile__wrap">
  3. <el-dialog
  4. :model-value="isVisibleC"
  5. :show-close="false"
  6. @close="close"
  7. title="上传文件"
  8. >
  9. <template #footer>
  10. <div class="dialog-footer">
  11. <el-button class="dialog-footer-cancel" @click="cancel">取消</el-button>
  12. <CpnWebUploader @butClickC='butClickC' :butTextC='选择上传的文件'></CpnWebUploader>
  13. </div>
  14. </template>
  15. </el-dialog>
  16. </div>
  17. </template>
  18. <script setup>
  19. import CpnWebUploader from '@/components/common/WebUploader.vue';
  20. // 子组件发射的@butClickC事件这里处理
  21. function butClickC() {
  22. }
  23. </script>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/66658
推荐阅读
相关标签
  

闽ICP备14008679号