element-ui 中不使用它的上传控件,利用原生 input
标签,隐藏其默认样式,采用自定义的方式上传:
<el-form-item label="文件上传和下载">
<el-input v-model="fileUrl" readonly></el-input>
<input type="file" id="file" accept="" @change="handleFileChange" />
<label class="el-button el-button--small" for="file"></label>
<el-button size="small" type="primary" @click="handleUpload">上传</el-button>
<el-button size="small" type="primary" @click="handleDownload">下载</el-button>
</el-form-item>
import { uploadFile, downloadFile } from '@/api'
import { saveAs } from '@/utils'
export default {
data() {
return {
fileUrl: '',
file: null
}
},
methods: {
handleFileChange(e) {
this.file = e.target.files[0]
this.fileUrl = this.file.name
}
async handleUpload() {
let name = 'image'
let filename = 'test.png'
await uploadFile(name, filename, this.file)
}
async handleDownload() {
let type = 'image'
let name = 'test.png'
const res = await downloadFile(type, name)
saveAs(res, 'download.png')
}
}
}
文件上传与后端约定 name
、filename
和 file
字段,其中 file 为文件流
// @/api/index.js
// 文件上传
export function uploadFile(name, filename, file) {
let formData = new FormData()
formData.append('name', name)
formData.append('filename', filename)
return $axios({
url: '/upload',
method: 'post',
data: formData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
文件下载服务端会返回文件流,约定 type
和 name
字段,设置相应类型 responseType: 'arraybuffer'
,设置响应头 Content-Type: 'application/octet-stream'
,告知浏览器这是一个字节流,浏览器处理字节流的默认方式就是下载
// @/api/index.js
// 文件下载
export function downloadFile(type, name) {
let formData = new FormData()
formData.append('type', type)
formData.append('name', name)
return $axios({
url: '/download',
method: 'post',
data: formData,
responseType: 'arraybuffer',
headers: {
'Content-Type': 'application/octet-stream'
}
})
}
文件下载需要获取服务传输的文件流,创建浏览器下载链接保存文件:
// @/utils/index.js
export const saveAs(buffers, name, mine = 'application/octet-stream') => {
const blob = new Blob([buffers], { type: mime })
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.setAttribute('download', name)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
}
$axios
方法是二次封装的 axios 实例:
// request.js
import axios from 'axios'
const baseURL = ''
const instance = axios.create({
baseURL,
timeout: 3000
})
export default instance