下载中:vue项目多个文件上传和下载

文件上传

上传文件是项目里经常遇到的需求,我之前基本上是碰到的单个文件上传,最近的项目有多个文件同时上传的需求并下载,遂记录一下。

注意:文件上传时必须使用FormData形式传参。

以Element-UI为例:

<el-form-item label="事件描述:" prop="parent_data.description" :label-width="formLabelWidth"> <el-input v-model="form.parent_data.description" placeholder="请输入事件背景,核心问题及解决要求" type="textarea" :autosize="{ minRows: 4, maxRows: 8}" autocomplete="off"/> <div class="fileContainer"> <el-upload ref="upload" class="upload-demo" action="#" :auto-upload="false" :on-change="selectFile" multiple :limit="3" :file-list="fileList" > <el-button size="small" type="primary">点击上传</el-button> <span slot="tip" class="el-upload__tip">单个附件大小不超过20M</span> </el-upload> </div></el-form-item>

 点击上传按钮选择文件(上传组件的使用方法请参考Element官网)

/* 选择上传文件 */selectFile(file, fileList) { this.fileList = fileListthis.fileList.map((item, index) => { const fileSize = item.size / 1024 / 1024 if (fileSize > 20) { this.$message.error('单个附件大小不能超过20M')this.fileList.splice(index, 1) } })},

将选择的文件保存到`fileList`数组中。有条件限制的可以在这处理。

我们知道上传文件时参数要用`FormData`形式传参,下一步就是把添加的文件放到`FormData`里面。

const fileData = new FormData()this.fileList.map((file,index)=>{ // data_report为请求接口时的参数,将文件存放到此参数中,多个文件会有多个data_report参数 // 这里添加的是file.raw,file格式文件(二进制) fileData.append('data_report', file.raw)})

例如,我一次上传两个文件,如图:

 当然有时候上传接口不止一个文件参数,还有其它参数,我们要把它们拼接起来。

const params = {...this.form, // 表单数据 parent_data: JSON.stringify(this.form.parent_data),// 其它参数creator_username: getUserInfo().name, // 其它参数job_num: getUserInfo().job_num, // 其它参数user_id: getUserInfo().userId // 其它参数 }

然后把上面的参数储存到`fileData`中

// 参数合并for (const key in params) {fileData.append(key, params[key])}// 现在`fileData`里包含了上传的文件参数和其它参数

最后就可以调用接口了

API.createList(fileData).then(async res => { // TODO})

文件下载

下载时怎么监听进度呢?

首先我们在封装下载接口时添加一个配置对象config,然后要指定服务器返回的数据类型:

// 下载附件export function downloadFile(data, config = {}) {return request({url: '/workflows/download_file/',method: 'post',data,responseType: 'blob', // 表明服务器返回的数据类型(文件流的形式)...config // config对象主要用来添加上传/下载附件监听})}

 点击下载按钮请求接口:

/* 下载附件 */downloadFile(item) {const that = thisconst params = {path: item.path}API.downloadFile(params, { // 文件下载监听 onDownloadProgress(progress) {const loading = that.$loading({ lock: true, text: '下载中...', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)'})// 下载进度const percent = Math.round((progress.loaded / progress.total) * 100) + '%'if (percent === '100%') {loading.close()}}}).then(res => { // 以流的形式返回的,这里没有code状态码const blob = new Blob([res.data])// 切割出文件名const fileNameEncode = res.headers['content-disposition'].split('filename=')[1]// 解码let fileName = decodeURIComponent(fileNameEncode)// 解码后的文件名会首尾多_,截取掉fileName = fileName.substring(1, fileName.length - 1)if (window.navigator.msSaveOrOpenBlob) {navigator.msSaveBlob(blob, fileName)} else {var link = document.createElement('a')link.href = window.URL.createObjectURL(blob)link.download = fileNamelink.click()// 释放内存window.URL.revokeObjectURL(link.href)}})},

相关推荐

相关文章