最近开发项目时,使用 element-plus 所遇到了一些坑,官方对于这块地方并没有很好的阐述,因此我这边自己总结了一下所遇到的问题。
1. 写在 el-upload 里面的任何按钮 都可以触发上传文件窗口
解决方案:
在你所需要的dom上,写一个防止冒泡的语句 ,比如我写的就是 @clickstop="" 这样就不会触发上传文件的窗口操作了
2. 绑定 fileList 后,为什么 remove 操作不会跟着改变 fileList 的值
这里其实 fileList 只是为了便于我们使用,给到的一个对象,文件列表,只有第一次渲染的是跟fileList 是对应的,后续的 remove 上传操作 ,都需要 我们根据 uploadFiles 自己维护这个 fileList 的值。
这里再阐述一下,文档里面标注的 uploadFile 和 uploadFiles 分别代表的是,当前操作的 文件对象 和 此时真正的 上传文件列表(里面包含了文件的字节信息等) 而不是 fileList
另外:upLoadFile 里面的 raw 才是真正的文件内容,自定义上传的传这个属性就行了
3. 多选上传后,触发多次 onchange 事件
这个会导致什么问题呢,我在写项目的时候,想着说 上传会触发 onchange 事件,是不是每次维护 fileList 的最后一个元素就行了,不是的,虽然会触发多次,第一个回调参数的 uploadFile 是对应一个个多选的文件,但是 uploadFiles 每次都是一样的
因此,我们根据对应的 name 去维护 fileList 的值就行了(在客户端名字是不会重复的)
4. 上传视频的时候,视频是没有缩略图的
为什么指定了,fileList 的 url 视频还是没有缩略图,因为上传列表 对应的是 uploadFiles 的内容。
因此我们需要 对应 修改 uploadFiles 的 url 就能给 视频加缩略图,自定义上传的时候,那么我们如果拿到 uploadFiles ,就能实现这个,只需要我们在 on-change 事件 和 remove 事件,都对 uploadFiles 进行引用,然后修改就行(因为复杂对象是 值传递,会对应修改 uploadFiles 的内容)
代码示例:
使用 tempUloadFiles 记录 每次的 uploadFiles , 这里的 generateVideo 函数 是通过 video 拿到视频第一帧的图片作为缩略图,代码我也贴在后面了
const handleChange = async (uploadFile, uploadFiles) => {
const url = await generateVideo(uploadFile.raw)
tempUploadFiles.value = uploadFiles
fileList.value.push({
name: uploadFile.name,
url: url,
raw: uploadFile.raw
})
// 实际渲染的是 uploadFiles 里面的url 而不是fileList的值
// 另外一个坑是 多选的时候触发俩次该函数,但是 uploadFiles 值是一样的,需要根据name取到下标
uploadFiles[uploadFiles.findIndex((item) => item.name === uploadFile.name)].url = url
// console.log(fileList.value)
}
async function generateVideoThumbnail(file) {
return new Promise((resolve, reject) => {
const videoUrl = URL.createObjectURL(file)
const video = document.createElement("video")
const canvas = document.createElement("canvas")
const ctx = canvas.getContext("2d")
video.src = videoUrl
video.muted = true
video.crossOrigin = "anonymous"
let completed = false
const captureFrame = () => {
if (completed) return
completed = true
try {
canvas.width = video.videoWidth
canvas.height = video.videoHeight
ctx.drawImage(video, 0, 0)
const thumbnailUrl = canvas.toDataURL("image/jpeg", 0.8)
URL.revokeObjectURL(videoUrl)
resolve(thumbnailUrl)
} catch (error) {
URL.revokeObjectURL(videoUrl)
reject(error)
}
}
video.addEventListener("loadeddata", () => {
video.currentTime = 1
})
video.addEventListener("seeked", async () => {
try {
// 短暂播放确保帧渲染
await video.play()
setTimeout(() => {
video.pause()
captureFrame()
}, 100)
} catch (error) {
// 如果播放失败,直接截图
captureFrame()
}
})
video.addEventListener("error", () => {
if (!completed) {
URL.revokeObjectURL(videoUrl)
reject(new Error("视频加载失败"))
}
})
setTimeout(() => {
if (!completed) {
URL.revokeObjectURL(videoUrl)
reject(new Error("操作超时"))
}
}, 8000)
video.load()
})
}
export default generateVideoThumbnail
5. 阿里云自定义上传如何拿到 进度条
在我们使用 官方 给到的 ali-oss 库时,进度条是需要调用 分片上传才能传回进度条
代码示例:
import OSS from "ali-oss";
const ossClient = axios.get(this.url).then(token=>{
this.client = new OSS({
// yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'yourregion',
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// 填写Bucket名称。
bucket: 'examplebucket',
});
const uploadPromises = fileList.value.map((file, index) => {
tempUploadFiles.value[index].status = "uploading"
return ossClient.client.multipartUpload(
"your-path/" + file.name,
file.raw || file, // 兼容不同格式
{
// 获取分片上传进度、断点和返回值。
progress: (p) => {
console.log(p)
tempUploadFiles.value[index].percentage = Math.round(p * 100, 2)
},
// 设置并发上传的分片数量。
parallel: 4,
// 设置分片大小。默认值为1 MB,最小值为100 KB,最大值为5 GB。最后一个分片的大小允许小于100 KB。
partSize: 1024 * 1024
}
)

1万+

被折叠的 条评论
为什么被折叠?



