在日常开发后台系统中,经常会涉及到文件图片上传,导入和文件下载。比如更换头像,批量导入数据,下载模版等等。上传地址环境一般分为公司内网和外网(如七牛云、阿里云),不同环境实现过程也是有区别的,在这里记录一下平时实现较多的方式,已便后期查阅。如有错误请多评论指正
内网环境
前言:为了提高开发效率和页面结构美观,直接选用UI库中上传组件,拿来即用,根据自己业务需求稍作修改即可。笔者写后台主要使用Ant Deaign Vue 和 Element UI
1.上传文件
-
template
<a-upload name="file" :file-list="fileList" action="#" :custom-request="customRequestUpload" :headers="headers" :remove="removeFiles" :before-upload="beforeUpload" @change="handleUploadChange" > <a-button :disabled="fileList.length>=20||fileList.some(s=>{return s.status==='uploading'})" size="small" type="dashed" > <a-icon type="upload" /> 点击上传 </a-button> <div style="color:#999;font-size:12px;marginTop:4px;">注:最多上传20个附件,每个附件不可大于200MB</div> </a-upload> -
javascript
data() { return { headers: { authorization: 'authorization-text' }, fileList: [] } }
// 上传前钩子
beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 200
if (!isLt2M) {
this.$message.error('文件大小不能超过200M!')
}
return isLt2M
},
// 上传文件状态改变触发,处理上传中加载显示
handleUploadChange(info) {
this.fileList = info.fileList.filter(f => f.status)
},
// 自定义上传方法
customRequestUpload(file) {
const formData = new FormData()
formData.append('file', file.file)
// 请求接口
uploadFiles(formData).then((res) => {
if (res.code === 0) {
this.fileList.push({
uid: `-${+new Date()}`,
status: 'done',
name: res.rows.fileName,
url: res.rows.downloadUrl,
fileMime: res.rows.contentType // 类型
})
this.fileList = this.fileList.filter((f) => f.status === 'done')
this.$message.success('上传成功')
} else {
this.$message.error(res.msg)
this.fileList = this.fileList.filter((f) => f.status === 'done')
}
}).catch(() => {}).finally(() => {})
}
2.导入文件
-
template
<el-upload action="#" :http-request="httpRequest" :before-upload="beforeAvatarUpload" :file-list="fileList" :before-remove="beforeRemove" > <el-button size="small" class="blue-btn" type="primary" icon="el-icon-upload"> 上传 </el-button> </el-upload> -
javascript
data() { return { fileList: [] } } // 文件上传之前的钩子 beforeAvatarUpload(file) { const fileReader = new FileReader() // FileReader读取文件内容 fileReader.readAsDataURL(file) // 转换成base64编码 const _that = this fileReader.onload = () => { _that.uploadData.file_data = fileReader.result.split('base64,')[1] _that.uploadData.file_name = file.name // 请求接口 _that.$fetch(_that.$api.uploadUrl, _that.uploadData).then(res => { if (res.code === '0000') { const result = [] result.push({ key: res.data.file_name, name: file.name }) _that.fileList = result } }).catch(() => { }) } }, httpRequest(data) {}, beforeRemove(file, fileList) { // 删除已上传的文件钩子 for (let i = 0; i < this.fileList.length; i++) { if (this.fileList[i].name === file.name) { this.fileList.splice(i, 1) } } }
外网环境
1.上传头像到七牛云
<!-- 更换头像 -->
<el-upload
:action="domain"
:data="QiniuData"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<el-avatar :size="100">
<img v-if="imageUrl" :loading="loading" :src="imageUrl" alt="">
<img v-else src="../../assets/img/avatar3.jpg">
</el-avatar>
<i class="el-icon-edit" />
</el-upload>
data() {
return {
QiniuData: {
key: '', // 图片名字处理
token: '' // 七牛云token
},
domain: 'https://upload.qiniup.com', // 七牛云的上传地址(华东区)
qiniuaddr: 'https://files.xxxx.cn', // 你的七牛云的图片外链地址
imageUrl: this.$store.state.user.avatar, // 头像路径
myDatas: { // 要传给后端的数据字段
user_token: getToken(),
avatar_uri: ''
}
}
}
// 头像上传
handleAvatarSuccess(response) { // 文件上传成功时的钩子
this.imageUrl = `${this.qiniuaddr}/${response.key}`
this.myDatas.avatar_uri = response.key
this.changePhoto()
this.resetSetItem('avatar', JSON.stringify(`${this.qiniuaddr}/${response.key}`))
},
beforeAvatarUpload(file) { // 上传文件之前的钩子
const isPNG = file.type === 'image/png'
const isJPEG = file.type === 'image/jpeg'
const isJPG = file.type === 'image/jpg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isPNG && !isJPEG && !isJPG) {
this.$message.error('上传头像图片只能是 jpg、png、jpeg 格式!')
return false
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
return false
}
// return isPNG && isJPEG && isJPG && isLt2M
return this.$fetch(this.$api.getQinniuToken, { user_token: getToken() }).then(res => {
this.QiniuData.token = res.data
this.QiniuData.key = moment(new Date()).format('YYYYMMDDHHmmss') + file.name // key为上传后的文件名
})
},
changePhoto() { // 提交-更新头像
// this.loading = true
this.$fetch(this.$api.updateAvatar, this.myDatas).then(res => {
if (res.code === '0000') {
this.loading = false
Message({
message: res.toast,
type: 'success',
duration: 3 * 1000
})
}
}).catch(err => {
this.loading = false
console.log(err)
})
}
main.js
// 监听
localStorageVue.prototype.resetSetItem = function(key, newVal) {
if (key === 'avatar') {
// 创建一个StorageEvent事件
var newStorageEvent = document.createEvent('StorageEvent')
const storage = {
setItem: function(k, val) {
localStorage.setItem(k, val)
// 初始化创建的事件
newStorageEvent.initStorageEvent('setItem', false, false, k, null, val, null, null)
// 派发对象
window.dispatchEvent(newStorageEvent)
}
}
return storage.setItem(key, newVal)
}}
2.上传文件到七牛云
<el-form-item ref="upload" label="上传" prop="item_template">
<el-upload
action="https://upload.qiniup.com"
:data="QiniuData"
:file-list="form.item_template"
:before-remove="beforeRemove"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<el-button size="small" class="green-btn" type="primary">
点击上传</el-button>
</el-upload>
</el-form-item>
data() {
return {
QiniuData: {
key: '', // 文件名字处理
token: '' // 七牛云token
},
qiniuaddr: 'https://files.xxxx.cn', // 你的七牛云的外链地址
item_template1: [], // 传后端的数据
fileName: ''
}
}
handleAvatarSuccess(response) { // 文件上传成功时的钩子
// 创建-要传递的模板json字符串
const item = { name: '', key: '' }
item.name = this.fileName
item.key = response.key
this.item_template1.push(item)
this.form.item_template.push(item)
this.$refs.upload.clearValidate()
},
beforeAvatarUpload(file) { // 上传文件之前的钩子
return this.$fetch(this.$api.getQinniuToken, { user_token: getToken() }).then(res => {
this.QiniuData.token = res.data
this.QiniuData.key = `${uuid.v1()}/${file.name}` // key为上传后的文件名
this.fileName = file.name
})
},
beforeRemove(file, fileList) { // 删除文件之前的钩子
for (let i = 0; i < this.item_template1.length; i++) {
if (this.item_template1[i].name === file.name) {
this.item_template1.splice(i, 1)
}
}
for (let i = 0; i < this.form.item_template.length; i++) {
if (this.form.item_template[i].name === file.name) {
this.form.item_template.splice(i, 1)
}
}
}
下载文件流
封装方法
export function fetchGet(url, params, wordName) {
const _params = params ? httpMd5(params) : {}
const word_name = `${wordName}-${timestampToTime(new Date())}${Math.floor(Math.random() * 100)}`
return axios({
method: 'GET',
url: `/api${url}`,
params: _params,
responseType: 'blob'
}).then(res => {
const blob = new Blob([res.data], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8'
})
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = word_name + '.docx' // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
}).catch(err => {
console.log(err)
})
}
export function fetchGetLog(url, params, wordName) {
const _params = params ? httpMd5(params) : {}
const word_name = `${wordName}-${timestampToTime(new Date())}${Math.floor(Math.random() * 100)}`
return axios({
method: 'GET',
url: `/api${url}`,
params: _params,
responseType: 'blob'
}).then(res => {
const blob = new Blob([res.data], { type: 'application/json;charset=utf-8' })
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = word_name + '.log' // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
}).catch(err => {
console.log(err)
})
}
export function fetchGetJson(url, params, wordName) {
const _params = params ? httpMd5(params) : {}
const word_name = `${wordName}-${timestampToTime(new Date())}${Math.floor(Math.random() * 100)}`
return axios({
method: 'GET',
url: `/api${url}`,
params: _params,
responseType: 'blob'
}).then(res => {
const blob = new Blob([res.data], { type: 'application/json;charset=utf-8' })
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = word_name + '.json' // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
}).catch(err => {
console.log(err)
})
}
export function fetchGetXlsx(url, params, wordName) {
const _params = params ? httpMd5(params) : {}
const word_name = `${wordName}-${timestampToTime(new Date())}${Math.floor(Math.random() * 100)}`
return axios({
method: 'GET',
url: `/api${url}`,
params: _params,
responseType: 'arraybuffer' // 返回数据的格式
}).then(res => {
const blob = new Blob([res.data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
})
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = word_name + '.xls' // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
}).catch(err => {
console.log(err)
})
}
引用
// 目标域名log下载
targetDomainLog(ID, Domian) {
this.$fetchGetLog(this.$api.targetDomainLog, { user_token: getToken(), target_id: ID }, `${this.taskName}-目标域名/网站${Domian}`)
}
其他
main.js将方法注册到vue原型
import { fetchGet, fetchGetLog, fetchPost, fetchGetXlsx, fetchGetJson } from './utils/request'
Vue.prototype.$fetchGet = fetchGet
Vue.prototype.$fetchGetLog = fetchGetLog
Vue.prototype.$fetchPost = fetchPost
Vue.prototype.$fetchGetXlsx = fetchGetXlsx
Vue.prototype.$fetchGetJson = fetchGetJson