经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)
来源:jb51  时间:2019/10/15 11:01:33  对本文有异议

说在前面

网上有很多种文件上传的方法,根据公司最近的业务需求,要求实现多种文件的上传,在实现过程中,查阅了很多资料,最后,终于把功能实现了,开心!

  1. <template>
  2. <div>
  3. <v-header :left-text="`上传${columnName}`"></v-header>
  4.  
  5. <div class="upload">
  6. <div v-if="columnName === '视频'">
  7. <div class="forPreview_video" v-for="(item, index) in uploadVideoList" :key="index">
  8. <video :src="videoSrc"></video>
  9. <van-icon name="delete" @click="delBtn(index)" class="delte"/>
  10. </div>
  11. <van-uploader v-show="uploadVideoList.length < 2" preview-size="80px" accept="video/*" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
  12. </div>
  13.  
  14. <div v-if="columnName === '文档'">
  15. <div class="forPreview_doc" v-for="(item, index) in uploadDocList" :key="index">
  16. <img src="../../assets/img/resource_doc_b@2x.png" alt="">
  17. <span>{{item.name}}</span>
  18. <span>{{item.size | formatSize}}</span>
  19. <van-icon name="delete" @click="delBtn(index)" class="delte"/>
  20. </div>
  21. <van-uploader v-show="uploadDocList.length < 2" preview-size="80px" accept=".doc, .docx, .xml, .xlsx, .pdf" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
  22. </div>
  23.  
  24. <div v-if="columnName === '音频'">
  25. <div class="forPreview_audio" v-for="(item, index) in uploadAudioList" :key="index">
  26. <img src="../../assets/img/resource_audio@2x.png" alt="">
  27. <span>{{item.name}}</span>
  28. <span>{{item.size | formatSize}}</span>
  29. <van-icon name="delete" @click="delBtn(index)" class="delte"/>
  30. </div>
  31. <van-uploader v-show="uploadAudioList.length < 2" preview-size="80px" accept="audio/*" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
  32. </div>
  33.  
  34. <div v-if="columnName === '图片'">
  35. <div class="forPreview_pic" v-for="(item, index) in uploadPicList" :key="index">
  36. <img :src="picSrc" alt="">
  37. <van-icon name="delete" @click="delBtn(index)" class="delte"/>
  38. </div>
  39. <van-uploader v-show="uploadPicList.length < 2" accept="image/*" preview-size="80px" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
  40. </div>
  41.  
  42. <div class="diy-submit">
  43. <van-button @click="doSubmit($event)">提交</van-button>
  44. </div>
  45. </div>
  46. </div>
  47. </template>

上述html代码是在同一页面根据前一页面传回的columnName的值来判断需要上传哪种类型文件。

  1. <script>
  2. import VHeader from '../../common/header'
  3. import {classifyList, uploadFile, addResources} from '../../http/mock'
  4. import Toast from 'vant'
  5. export default {
  6. name: "uploadFile",
  7. components: {
  8. VHeader
  9. },
  10. data(){
  11. return{
  12. tagList: [],
  13. uploadTitle: '',
  14. currentTag: null,
  15. tagId: null,
  16. columnName: localStorage.getItem('columnName'),
  17. fileIdArr: [],
  18.  
  19. uploadVideoList: [], // 选中的上传视频列表
  20. videoSrc: '', // 选中的视频的src,用来显示视频
  21. uploadDocList: [], // 选中的上传文档列表
  22. uploadAudioList: [], // 选中的上传音频列表
  23. uploadPicList: [], // 选中的上传图片列表
  24. picSrc: '', // 选中的图片的src,用来显示图片缩略图
  25. }
  26. },
  27. filters: {
  28. formatSize(val) { // 格式化文件大小
  29. if (val > 0) {
  30. return (val / 1024 / 1024).toFixed(2) + 'M';
  31. } else {
  32. return '0M';
  33. }
  34. },
  35. },
  36. methods: {
  37. // vant上传文件前校验文件事件
  38. // 文件选中后先提交给后台,后台根据选中的文件,返回数组(这一业务根据后台而定)
  39. beforeRead(file){
  40. let formData = new FormData(); // 为上传文件定义一个formData对象
  41. let config = {
  42. headers: {
  43. 'Content-Type': 'multipart/form-data'
  44. }
  45. };
  46. let uploadUrl = URL.createObjectURL(file); // 将选中的上传文件转化为二进制文件,显示在页面上
  47. if(this.columnName === '视频'){
  48. this.uploadVideoList.push(file);
  49. this.videoSrc = uploadUrl;
  50. // 这里使用foreach是为了将选中的多个文件都添加进定义的formdata变量中
  51. this.uploadVideoList.forEach(item => {
  52. formData.append(item.name, item)
  53. })
  54. }else if(this.columnName === '文档'){
  55. this.uploadDocList.push(file);
  56. this.uploadDocList.forEach(item => {
  57. formData.append(item.name, item)
  58. })
  59. }else if(this.columnName === '音频'){
  60. this.uploadAudioList.push(file);
  61. this.uploadAudioList.forEach(item => {
  62. formData.append(item.name, item)
  63. })
  64. }else if(this.columnName === '图片'){
  65. this.uploadPicList.push(file);
  66. this.picSrc = uploadUrl;
  67. this.uploadPicList.forEach(item => {
  68. formData.append(item.name, item)
  69. })
  70. }
  71.  
  72.  
  73. // formData.append(file.name, file); // 单个文件上传时可以这么写,上面的foreach就可以删掉
  74. this.$api.post(uploadFile, formData, config).then(res => {
  75. this.fileIdArr = res.data.data; // 把選中的文件傳送給後台
  76. }).catch(err => {
  77. Toast('文件上傳失敗!')
  78. })
  79. },
  80. // 删除待上传的文件
  81. delBtn(index){
  82. if(this.columnName === '视频'){
  83. // 先判断当前的选中的索引是否是在有效范围中,如果不是则跳出方法
  84. if(isNaN(index) || index >= this.uploadVideoList.length){
  85. return false;
  86. }
  87. let tmp = [];
  88. // 将没被选中的上传文件存放进一个临时数组中
  89. for(let i = 0; i < this.uploadVideoList.length; i++){
  90. if(this.uploadVideoList[i] !== this.uploadVideoList[index]){
  91. tmp.push(this.uploadVideoList[i]);
  92. }
  93. }
  94. // 存放当前未被选中的上传文件
  95. this.uploadVideoList = tmp;
  96. }
  97.  
  98. if(this.columnName === '文档'){
  99. console.log(this.uploadDocList.length)
  100. if(isNaN(index) || index >= this.uploadDocList.length){
  101. return false;
  102. }
  103. let tmp = [];
  104. for(let i = 0; i < this.uploadDocList.length; i++){
  105. if(this.uploadDocList[i] !== this.uploadDocList[index]){
  106. tmp.push(this.uploadDocList[i]);
  107. }
  108. }
  109. this.uploadDocList = tmp;
  110. }
  111.  
  112. if(this.columnName === '音频'){
  113. if(isNaN(index) || index >= this.uploadAudioList.length){
  114. return false;
  115. }
  116. let tmp = [];
  117. for(let i = 0; i < this.uploadAudioList.length; i++){
  118. if(this.uploadAudioList[i] !== this.uploadAudioList[index]){
  119. tmp.push(this.uploadAudioList[i]);
  120. }
  121. }
  122. this.uploadAudioList = tmp;
  123. }
  124.  
  125. if(this.columnName === '图片'){
  126. if(isNaN(index) || index >= this.uploadPicList.length){
  127. return false;
  128. }
  129. console.log('uuu')
  130. let tmp = [];
  131. for(let i = 0; i < this.uploadPicList.length; i++){
  132. if(this.uploadPicList[i] !== this.uploadPicList[index]){
  133. tmp.push(this.uploadPicList[i]);
  134. }
  135. }
  136. this.uploadPicList = tmp;
  137. }
  138. },
  139. doSubmit(){
  140. let params = {
  141. classify: this.tagId, // 针对视频资源时对应的分类id
  142. file: this.fileIdArr, // 选择完文件后,调用uploadFile这个接口,后端返回的数组
  143. resourceColumnId: JSON.parse(localStorage.getItem('columnId')), // 资源栏目id(视频、图片、音频、文档)
  144. title: this.uploadTitle // 上传时填写的标题
  145. };
  146. let columnName = localStorage.getItem('columnName')
  147. this.$api.post(addResources, params).then(res => {
  148. if(res.data.code === 1001){
  149. if(columnName === '视频'){
  150. this.$router.push({name: 'myVideo'});
  151. }else {
  152. this.$router.push({name: 'myResourceClassify'});
  153. }
  154. }
  155. }).catch(err => {
  156. console.log(err)
  157. })
  158. },
  159. },
  160. mounted(){
  161. this.getClassifyList();
  162. }
  163. }
  164. </script>
  165. <style lang="less" scoped>
  166. .upload{
  167. padding: 140px 36px 160px 36px;
  168. box-sizing: border-box;
  169. }
  170.  
  171. .forPreview_video{
  172. position: relative;
  173. /*background: rgba(0,0,0,.7);*/
  174. video{
  175. width: 95%;
  176. max-height: 430px;
  177. }
  178. .delte{
  179. position: absolute;
  180. right: 0;
  181. bottom: 0;
  182. }
  183. }
  184. .forPreview_doc, .forPreview_audio{
  185. display: flex;
  186. margin-bottom: 10px;
  187. align-items: center;
  188. img{
  189. width: 56px;
  190. height: 56px;
  191. margin-right: 20px;
  192. }
  193. span:nth-of-type(1){
  194. flex: 1;
  195. }
  196. span:nth-of-type(2){
  197. margin-right: 20px;
  198. }
  199. }
  200. .forPreview_pic{
  201. display: flex;
  202. align-items: flex-end;
  203. img{
  204. width: 160px;
  205. height: 160px;
  206. }
  207. }
  208.  
  209. .diy-detail{
  210. width: 100%;
  211. overflow: hidden;
  212. .btn{
  213. span{
  214. margin-bottom: 10px;
  215. }
  216. }
  217. .van-cell{
  218. background-color: #F0F0F0;
  219. border-radius: 35px;
  220. font-size: 26px;
  221. height: 69px;
  222. line-height: 69px;
  223. padding: 0 22px;
  224. color: #999;
  225. }
  226. .van-hairline--top-bottom::after, .van-hairline-unset--top-bottom::after {
  227. border-width: 0;
  228. }
  229. p{
  230. height: 64px;
  231. line-height: 64px;
  232. font-size: 32px;
  233. color: #333;
  234. position: relative;
  235. padding-left: 16px;
  236. }
  237. p::before{
  238. position: absolute;
  239. top: 0;
  240. left: 0;
  241. content: '*';
  242. color: #FF0000;
  243. }
  244.  
  245. span{
  246. display: inline-block;
  247. width: 157px;
  248. background: #F0F0F0;
  249. border-radius: 35px;
  250. color: #999;
  251. font-size: 26px;
  252. padding: 14px 18px;
  253. margin-right: 28px;
  254. text-align: center;
  255. }
  256. .active{
  257. color: #fff;
  258. background: linear-gradient(to right,#FD5130,#FA6C34);
  259. }
  260. }
  261. .diy-submit {
  262. position: fixed;
  263. height: 150px;
  264. width: 90%;
  265. bottom: 0;
  266. background: #fff;
  267.  
  268. .van-button {
  269. width: 100%;
  270. height: 90px;
  271. border-radius: 45px;
  272. font-size: 36px;
  273. color: #fff;
  274. background: linear-gradient(to right, #FD5130, #FA6C34);
  275. top: 50%;
  276. transform: translate(0, -50%);
  277. }
  278. .van-button--default {
  279. border: none;
  280. }
  281. }
  282. </style>
  283.  

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号