Skip to main content

Vue3 uses van-uploader to solve the problem that some Android models (Xiaomi, vivo, oppo, etc.) cannot upload files

summary

Recently, when I was working on a mobile terminal, I encountered a need to upload attachments. Only the following types of files can be uploaded:

Image files (jpeg, jpg, png)

Document files (pdf, txt, doc, docx, xls, xlsx, ppt, pptx)

Here I used Youzan's upload component, but after going online, I found that there was no problem with Apple phones , but some Android phones had problems. After several modifications and adjusting the restricted file types, uploading was normal! ! ! Congratulations, I recorded the solution here, hoping it can help everyone.

Corresponding attachment format

Image format (limited to png, jpeg, png)

accept="image/jpeg,image/png,image/jpg"
jpeg:image/jpeg
png:image/png
jpg:image/jpg

File format (limited to pdf, doc, docx, ppt, pptx, xls, xlsx)

pdf: application/pdf
doc: application/msword
docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document
ppt: application/vnd.ms-powerpoint
pptx: application/vnd.openxmlformats-officedocument.presentationml.presentation
xls: application/vnd .ms-excel
xlsx:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

Text format (limited to txt)

txt: text/plain

File format (limited to zip and rar)

zip:application/zip
rar:application/x-rar-compressed

Component encapsulation

Tip: This is used to determine whether there are restriction types and whether the file size meets the standards

<template>
<van-uploader
ref="uploaderRef"
:before-read="beforeRead"
:accept="acceptType"
:max-size="maxSize"
:max-count="maxCount"
preview-size="55px"
>
<span class="text">{{
text
}}</span>
</van-uploader>
</template>

<script lang="ts" setup>
import { Notify, Toast } from 'vant'
import fileApi from '~/api/file'
const uploaderRef = ref() // 文件实例
interface uploadProps {
acceptType?: string // 接受类型
limit?: number // 限制文件个数
maxSize?: number // 文件大小限制
text?: string
fileExtension?: string // 文件后缀名
imgExtension?: string // 图片后缀名
maxCount?: number
}

interface fileItem {
fileName: string
fileUrl: string
fileType: string
size: number
isImage?: boolean
id?: string
businessId?: string
createTime?: string
unit?: string
}

const emits = defineEmits(['success', 'delete',])
const props = withDefaults(defineProps<uploadProps>(), {
text: '上传附件',
limit: 10,
maxSize: 200,
maxCount: 99,
acceptType:
'image/jpeg, image/jpg, image/png, text/plain, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation ,application/pdf',
fileExtension: 'pdf, txt, doc, docx, xls, xlsx, ppt, pptx',
imgExtension: 'jpeg/jpg/png',
fileList: () => [],
showUploadBtn: true,
type: 'add',
})

// 获得文件后缀名
const getFileExtension = (name: string) => {
const extension = name.substring(name.lastIndexOf('.') + 1).toLowerCase() // 文件后缀
return extension
}

// 文件上传钩子
const beforeRead = (file: any) => {
const extension = file.name
.substring(file.name.lastIndexOf('.') + 1)
.toLowerCase() // 文件后缀

// 判断是否图片类型
const isImage = props.imgExtension.includes(extension)
// 判断是否超过最大上传限制,当前限制了200m
const isMax = file.size / 1024 / 1024 < props.maxSize
if (!isMax) {
Notify({
type: 'danger',
message: `文件大小上限为${props.maxSize}M`,
duration: 1000,
})
return false
}
// 限制上传类型
const isLimit = props.fileExtension.includes(extension) || props.imgExtension.includes(extension)
if (!isLimit) {
Notify({
type: 'danger',
message: `文件上传格式不正确`,
duration: 1000,
})
return false
}
// 通过校验后执行上传文件方法
uploadFile(file)
return true
}

// 唤醒上传文件功能
const openUploader = () => {
uploaderRef.value.chooseFile()
}

const deleteList = (index: number) => {
emits('delete', index)
}

// 上传文件
const uploadFile = async (file: File) => {
Toast.loading({
duration: 0,
message: '上传中...',
forbidClick: true,
})
const formData = new FormData()
formData.append('file', file)
formData.append('transfer', '0')
const { code, data } = await fileApi.uploadFile(formData) // 这里替换成实际项目中的api名称
const extension = file.name
.substring(file.name.lastIndexOf('.') + 1)
.toLowerCase() // 文件后缀
const isImage = props.imgExtension.includes(extension)
if (code.value === 0) {
const fileData = {
fileName: file.name,
fileUrl: data.value.message, // 图片回显
size: file.size,
fileType: getFileExtension(file.name),
isImage,
unit: 'KB',
}
// 抛出成功信息
emits('success', fileData)
Notify({
type: 'success',
message: `上传成功`,
duration: 1000,
})
Toast.clear()
return true
} else {
Notify({
type: 'danger',
message: `上传失败`,
duration: 1000,
})
Toast.clear()
}
}

defineExpose({
openUploader,
})
</script>
<style lang="less" scoped>
.text {
color: #86909c;
font-size: 15px;
display: inline-block;
}
</style>