vant-uploader实现formData图片上传

本文详细介绍了 vant-uploader 组件在Vue.js项目中的应用,包括如何实现图片上传、限制上传数量、删除图片功能。通过示例代码展示了单张与多张图片上传的处理方式,并使用axios进行文件上传,同时对上传后的图片数量进行了限制和处理。
## vant-uploader图片上传
<van-col span="24" class="filed">
 <van-col span="24" class="info_img">店铺照片:</van-col>
 <div class="img_box">
  <div class="upload_images" v-for="(item,index) in picture_list" :key="index">
   <img class="image" :src="item"/>
   <div class="icon_close" @click="deleteImg(index)">X</div>
  </div>
  <van-uploader :after-read="uploadFn"
   max-count="5"
   multiple
  />
 </div>
</van-col>
js代码
//上传
      uploadFn(file){
        let formData = new FormData();
        if(file instanceof Array&&file.length){//多图
          for (let i = 0; i < file.length; i++) {
            const element = file[i].file;
            formData.append(["file"+'['+[i]+']'],element);//添加
          }
        }else{//单张
           formData.append(["file"+'['+[0]+']'],file.file);
        }
         axios({
            method: 'post',
            url: '/api/magic_mirror/uploadFile',
            data: formData
          }).then(res => {
            if(res.status==200){
              let total=this.picture_list.length+res.data.data.length;
              if(total>5){//处理图片最多可上传5张
                let Length=(res.data.data.length+this.picture_list.length)-5;
                let num=res.data.data.length-Length;
                let arrImg=res.data.data.splice(0,num);
                this.picture_list.push(...arrImg);
              }else{
                this.picture_list.push(...res.data.data);
              }
            }
          }).catch((err) => {
            console.log(err);
          })
      },
  首先创建formData对象用于存储图片
  uploadFn回调file为当前上传的图片
  单张返回对象,多个返回数组
  instanceof用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
  用于区分单张还是多张
  单张--直接append添加
  多张--循环回调数组,依次把每个图片添加进去
  这里上传用的axios(封装过的接口会有小问题,不做过多阐述),data直接把formData对象传过去
成功回调status200,push进数组循环出即可
删除splice当前选择元素即可
由于van-uploader没有绑定v-model,图片上传前数量自行判断即可

<think>我们正在处理一个关于Vant的van-uploader组件的问题。用户希望知道如何配置该组件以支持非图片文件的上传。根据引用内容,van-uploader通常用于图片上传,但我们需要让它支持其他类型的文件。 分析引用内容: 引用[1]和[2]展示了van-uploader用于图片上传的典型用法,包括使用after-read事件处理上传逻辑。引用[3]则提供了一种通过两个uploader组件重叠来实现编辑图片的思路。 然而,这些引用都没有直接说明如何支持非图片文件。因此,我们需要基于van-uploader的文档和特性来寻找解决方案。 根据Vant官方文档(尽管未直接引用,但我们可以根据组件特性推断): - van-uploader组件默认支持图片预览,但它也可以用于上传其他类型的文件。关键在于如何设置accept属性以及如何处理文件。 步骤: 1. 设置accept属性:accept属性用于指定接受的文件类型。我们可以设置为`*`(所有文件)或者特定的MIME类型,例如`.pdf`用`application/pdf`。 2. 在after-read事件中,我们获取到的文件对象(file.file)是一个File对象,我们可以根据这个对象的类型来判断并处理上传。 但是,非图片文件无法预览,所以我们需要考虑显示一个默认的文件图标,并显示文件名。 此外,我们可能还需要修改上传逻辑,因为非图片文件的上传可能和图片一样(都是通过FormData),所以服务器端也需要支持。 因此,我们可以这样实现: 模板部分: 我们可以设置accept属性,例如`accept=".pdf,.doc,.docx"`,这样用户可以选择这些类型的文件。同时,我们可能希望自定义预览显示,因为非图片文件无法显示图片预览。 Vant的van-uploader组件提供了默认插槽可以自定义预览样式。我们可以通过判断文件类型来显示不同的图标和文件名。 但是,请注意,van-uploader组件的v-model绑定的是fileList,它是一个数组,每个元素包含以下属性: - content: 用于图片预览的base64数据(仅当文件是图片时生成) - file: 文件对象 - status: 状态(如uploading, done, failed) - message: 状态信息 对于非图片文件,content可能为空(或者不会生成预览图)。因此,我们可以使用file对象来获取文件名,并显示一个对应文件类型的图标。 具体步骤: 1. 设置accept属性,允许选择非图片文件。 2. 使用自定义预览模式(通过插槽),根据文件类型显示不同的图标和文件名。 示例代码: 模板: ```html <van-uploader v-model="fileList" :after-read="afterRead" :max-count="1" accept="*" <!-- 接受所有类型,也可以指定如".pdf,.doc,.docx" --> > <!-- 自定义预览区域 --> <template #preview-cover="{ file }"> <!-- 这里我们覆盖默认的预览样式,如果是图片则显示图片,否则显示文件图标 --> <!-- 但是注意,van-uploader的预览插槽是用于在预览图上覆盖内容的,不适合完全替换预览样式。 --> <!-- 因此,另一种方法是使用file-list插槽完全自定义文件列表的显示 --> </template> </van-uploader> ``` 然而,更彻底的自定义是使用`file-list`插槽(Vant 3.0以上支持)来完全控制文件列表的显示。 在Vant 3中,我们可以这样: ```html <van-uploader v-model="fileList" :after-read="afterRead" :max-count="1" accept="*"> <template #file="{ file }"> <!-- 自定义每个文件项的显示 --> <div class="custom-file-item"> <van-icon name="description" v-if="file.file && !isImage(file.file)" /> <img v-else :src="file.content" class="van-uploader__preview-image"> <span class="file-name">{{ file.file ? file.file.name : '' }}</span> </div> </template> </van-uploader> ``` 注意:上面的代码中,我们假设有一个方法`isImage`来判断文件是否为图片。 在methods中定义isImage方法: ```javascript methods: { isImage(file) { return file.type.startsWith('image/'); } } ``` 这样,如果是图片则显示图片预览,否则显示一个文件图标和文件名。 另外,上传逻辑(afterRead方法)和图片上传是一样的,因为都是通过FormData上传。所以服务器端需要能够处理各种类型的文件。 但是,注意非图片文件可能比较大,需要在上传时显示上传进度等,但van-uploader默认不提供进度条。如果需要,可能需要自己实现。 总结配置步骤: 1. 设置accept属性,指定允许的文件类型。 2. 使用file-list插槽自定义文件列表的显示,以支持非图片文件的显示。 3. 上传逻辑(afterRead)和图片上传一致,但要注意服务器端支持。 注意:van-uploader组件本身并不限制文件类型,它只是在前端选择文件时过滤。所以核心是accept和自定义显示。 另外,如果不需要预览,也可以设置`preview-image`属性为false,然后完全使用自定义的显示。 但是,如果用户希望在上传前就显示文件图标(而不是上传后),那么我们可以通过监听文件选择变化,然后手动构建fileList(包含文件对象和自定义的预览内容)来实现。 不过,van-uploader的after-read事件会在选择文件后触发,我们可以在该事件中获取文件,然后根据文件类型设置一个预览内容(比如设置一个文件类型的图标URL),这样在fileList中就会显示这个图标。 例如,在afterRead中: ```javascript afterRead(file) { // 如果是非图片,我们可以设置一个默认的图标作为预览图 if (file.file && !file.file.type.startsWith('image/')) { // 这里我们生成一个文件图标的URL(可以是本地的一个图标,或者根据文件类型动态选择) // 注意:我们不能直接修改file.content,因为它是只读的?但是我们可以修改file对象,添加一个自定义属性,然后在模板中使用。 // 但是,van-uploader的fileList中的每个文件对象是只读的,所以我们不能直接修改。我们可以重新构建fileList。 // 另一种做法:在after-read中,我们上传文件,然后服务器返回文件地址,但非图片文件我们不需要预览图,所以我们可以在上传成功后,将fileList中对应文件的content设置为一个文件图标(本地图标)的base64或者URL。 // 但是,这样比较复杂。所以更推荐使用自定义插槽来显示。 // 因此,我们这里不做修改,而是通过自定义插槽来显示,因为插槽中我们可以根据文件类型显示不同的内容。 } // 上传逻辑 ... } ``` 因此,我们回到自定义插槽的方案,这是最直接的方法。 最后,注意van-uploader的删除事件(delete)也需要处理,通常我们只需要从fileList中移除即可,因为v-model绑定,所以会自动更新。 所以,完整的示例代码: ```html <template> <van-uploader v-model="fileList" :after-read="afterRead" @delete="handleDelete" :max-count="1" accept="*" <!-- 接受所有文件类型 --> > <template #file="{ file }"> <div class="custom-file-item"> <!-- 如果是图片,显示图片预览 --> <img v-if="isImage(file.file)" :src="file.content" class="van-uploader__preview-image"> <!-- 否则,显示文件图标 --> <van-icon v-else name="description" size="50" /> <div class="file-name">{{ file.file.name }}</div> </div> </template> </van-uploader> </template> <script> export default { data() { return { fileList: [] }; }, methods: { isImage(file) { return file && file.type.startsWith('image/'); }, afterRead(file) { // 此时file是选中的文件对象,注意file参数有两种情况:单个文件对象或多个文件数组(当multiple为true时) // 因为我们设置了max-count=1,所以这里只可能是单个文件 // 构造FormData let formData = new FormData(); formData.append("file", file.file); // 调用上传API // 假设有一个upload方法,返回一个promise upload(formData).then(res => { this.$toast.success(res.msg); // 上传成功,将返回的url保存到需要提交的表单字段中,例如info.payAvg if (res.url) { // 这里假设我们有一个info对象存储表单数据 this.info.payAvg = res.url; } }).catch(err => { this.$toast.fail('上传失败'); }); }, handleDelete() { // 删除文件时,清空表单字段 this.info.payAvg = ''; } } }; </script> <style> .custom-file-item { display: flex; flex-direction: column; align-items: center; } .file-name { margin-top: 5px; font-size: 12px; color: #646566; } .van-uploader__preview-image { width: 100%; height: 100%; object-fit: cover; } </style> ``` 注意:上面的upload函数需要根据实际情况实现,例如使用axios等。 这样配置后,van-uploader就可以支持非图片文件的上传了,并且能够正确显示文件图标和文件名。 相关问题: 1. 如何限制van-uploader上传的文件类型? 2. 如何实现多文件上传? 3. 如何在上传非图片文件时显示上传进度?</think>要配置 Vant 的 `van-uploader` 组件支持非图片文件上传,需通过以下步骤实现: ### 解决方案 1. **设置 `accept` 属性** 指定允许上传的文件类型,支持 MIME 类型或文件扩展名: ```html <van-uploader v-model="fileList" :after-read="afterRead" accept=".pdf,.doc,.docx,.xls,.zip,application/*" :max-count="1" /> ``` - 示例:`accept=".pdf,.doc"` 或 `accept="application/pdf, application/msword"` 2. **自定义文件预览样式** 使用 `#file` 插槽覆盖默认预览样式,显示文件图标和名称: ```html <van-uploader v-model="fileList"> <template #file="{ file }"> <div class="custom-preview"> <van-icon name="description" size="40" /> <span>{{ file.file.name }}</span> </div> </template> </van-uploader> ``` 3. **上传逻辑处理(关键)** 在 `after-read` 事件中处理文件上传,注意**非图片文件不会生成预览图**: ```javascript async afterRead(file) { // file.file 是原生 File 对象 const formData = new FormData(); formData.append("file", file.file); // 注意用 file.file 不是 file.content try { const res = await uploadFile(formData); // 调用上传API this.fileList = [{ file: file.file, // 保留文件对象 status: 'done', // 标记上传完成 name: file.file.name // 文件名 }]; this.info.fileUrl = res.url; // 保存服务器返回的URL } catch (error) { this.$toast.fail("上传失败"); } } ``` 4. **删除文件处理** 重置文件列表和存储的URL: ```javascript handleDelete() { this.fileList = []; this.info.fileUrl = ""; } ``` ### 完整示例代码 ```html <template> <van-field name="document" label="上传文件"> <template #input> <van-uploader v-model="fileList" :after-read="afterRead" @delete="handleDelete" accept=".pdf,.doc,.xls,.zip,application/*" :max-count="1" > <template #file="{ file }"> <div class="custom-file"> <van-icon name="description" /> <span>{{ file.file.name }}</span> </div> </template> </van-uploader> </template> </van-field> </template> <script> export default { data() { return { fileList: [], info: { fileUrl: "" } }; }, methods: { async afterRead(file) { const formData = new FormData(); formData.append("file", file.file); // 关键:使用 file.file try { const res = await axios.post("/api/upload", formData); this.info.fileUrl = res.data.url; this.fileList = [{ file: file.file, status: "done", name: file.file.name }]; } catch (error) { this.$toast.fail("上传失败"); } }, handleDelete() { this.info.fileUrl = ""; } } }; </script> <style> .custom-file { display: flex; align-items: center; padding: 8px; } </style> ``` ### 注意事项 1. **服务器端配置**:确保服务器能处理非图片文件的上传请求,并正确返回文件 URL 2. **文件大小限制**:通过 `max-size` 属性限制文件大小(单位字节): ```html <van-uploader :max-size="10 * 1024 * 1024" /> <!-- 10MB --> ``` 3. **移动端适配**:添加 `capture` 属性可限制为文件选择(非相机): ```html <van-uploader capture="user" /> <!-- 在移动端触发文件选择 --> ``` > 通过以上配置,`van-uploader` 可支持 PDF、Word、Excel 等任意文件类型上传,关键点在于正确使用 `file.file` 获取原生文件对象而非依赖图片预览数据[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值