【uniapp】---- 使用 uniapp 实现视频和图片上传且都可以预览展示
1. 前言
接手得 uniapp 开发的微信小程序项目,新的开发需求是需要同时上传图片和视频,但是之前的上传都没有进行封装,都是每个页面需要的时候单独实现,现在新的需求,有多个地方都需要上传图片、视频或语音等,这样就需要封装一个组件,然后发现部分地方使用了 uni-file-picker 组件,但是 uni-file-picker 在 grid 的时候只能进行图片的展示,如果是 video 或者 all 的时候,就会直接列表展示的文件名列表,不满足我当前的需求,因此在 uni-file-picker 基础上进行再次适配当前需求的封装。
2. 实现效果
3. 分析
- 图片和视频同时预览展示,就需要判断上传的是否是视频或者图片;
- 根据接口判断是否上传文件的格式是否在允许范围内;
- 使用 uni-file-picker 需要改造,将文件预览列表隐藏,使用自定义的预览文件。
4. 判断是图片
export const isImageFile = (filename) => {// 定义常见的图片文件扩展名const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']// 获取文件扩展名const fileExtension = filename.split('.').pop().toLowerCase()// 判断文件扩展名是否在图片扩展名列表中return imageExtensions.includes(fileExtension)
}
5. 判断是视频
// 判断是不是视频
export const isVideoFile = (filename) => {// 定义常见的视频文件扩展名const videoExtensions = ['mp4','avi','mov','mkv','flv','wmv','webm','mpeg','mpg']// 获取文件扩展名const fileExtension = filename.split('.').pop().toLowerCase()// 判断文件扩展名是否在视频扩展名列表中return videoExtensions.includes(fileExtension)
}
6. 根据接口判断是否是可上传格式文件
export const canUploadFile = (filename) => {const extensions = ['bmp','gif','jpg','jpe','png','mp4','mp3']// 获取文件扩展名const fileExtension = filename.split('.').pop().toLowerCase()// 判断文件扩展名是否在视频扩展名列表中return extensions.includes(fileExtension)
}
7. 预览图片和视频
uploadPreview 插槽是方便自定义预览,这里我是用 tailwindcss 实现了一个默认的视频和图片的预览样式。
<slot name="uploadPreview"><view class="cc mr-[20rpx] wh-[160] bd-[8] flex-none relative" v-for="(item,index) in fileLists" :key="item.url"><view class="icon-del-box" @click.stop="deletePic(item)"><view class="icon-del"></view><view class="icon-del rotate"></view></view><image v-if="item.isImage" :src="item.url" class="wh-[160] bd-[8] flex-none"></image><video v-else-if="item.isVideo" :src="item.url" class="wh-[160] bd-[8] flex-none"></video></view>
</slot>
8. 使用 uni-file-picker 上传
- 注意:是对 list 模式的文件上传,所以直接将 mode 的值写死 list;
- uploadButtom 自定义上传样式。
<uni-file-picker:limit="limit":file-mediatype="fileMediatype"@select="getUpload":is-upload-file="false":autoUpload="false"mode="list":value="fileLists"
><slot name="uploadButtom"><viewclass="cc bg-[#F9F9F9] wh-[160] bd-[8] b-[2rpx_#D0D0D0_dashed] flex-none"><image :src="$icon.publishAddIcon" class="wh-[48]"></image></view></slot>
</uni-file-picker>
9. 完整组件实现
<template><view class="ac"><slot name="uploadPreview"><view class="cc mr-[20rpx] wh-[160] bd-[8] flex-none relative" v-for="(item,index) in fileLists" :key="item.url"><view class="icon-del-box" @click.stop="deletePic(item)"><view class="icon-del"></view><view class="icon-del rotate"></view></view><image v-if="item.isImage" :src="item.url" class="wh-[160] bd-[8