文件上传

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

注意:文件上传时必须使用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 = fileList
	this.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 = this
	const 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 = fileName
					link.click()
					// 释放内存
					window.URL.revokeObjectURL(link.href)
				}
			})
		},

Logo

前往低代码交流专区

更多推荐