前端-vue-文件上传(图片、word,ppt,pdf,excel,txt等文件流)
1. 文件上传(图片、word,ppt,pdf,excel,txt等文件流)总结一下上传组件的思路input标签的@change事件通过input标签的@change事件的绑定,进行文件的选择上传,获取到文件const uploadFile = file.target.files[0],然后通过文件流转为base64,然后可以在前端进行预览。预览只有图片和PDF预览的文件不多,只有img,和pdf
1. 文件上传(图片、word,ppt,pdf,excel,txt等文件流)
总结一下上传组件的思路
-
input标签的@change事件
-
通过input标签的@change事件的绑定,进行文件的选择上传,获取到文件
const uploadFile = file.target.files[0]
,然后通过文件流转为base64,然后可以在前端进行预览。 -
预览只有图片和PDF
-
预览的文件不多,只有img,和pdf的可以预览,这和浏览器可以打开的文件流有关,前端能做到的预览只有图片和PDF,像word、和ppt、excel等不可前端预览,需要后端解析,重新返回相应地址方可预览
-
word、和ppt、excel的预览需要后端做出相应的处理,这些文件返回的地址是处理过的,预览地址和下载地址是不一样的
-
后端给的文件地址必须公网
-
微软解析地址:https://view.officeapps.live.com/op/view.aspx?src=你的文件地址
-
上传的子组件
<template>
<div class="addAttachments">
<el-dialog title="上传附件" v-model="dialogFormVisible" >
<div class="upload-wrap">
<input
class="input"
type="file"
ref="uploadInput"
@change="handleChange($event,photoName)"
/>
<el-button type="primary" size="small" @click="submitClick">选择文件</el-button>
</div>
<!-- 上传的内容 -->
<div class="addAttachments-content">
<el-table :data="gridData" height="400" v-loading="loading" element-loading-text="图片上传中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)">
<el-table-column property="name" label="名称" ></el-table-column>
<el-table-column property="localsize" label="大小" width="200">
<template #default="scope">
<span >
{{formatMoney(scope.row.localsize)}}kb
</span>
</template>
</el-table-column>
<!-- 由于文件未真正上传,所以无法预览word、ppt文档,所以预览功能暂时先隐藏 -->
<!-- <el-table-column property="localurl" label="地址" width="200">
<template #default="scope">
<el-button @click.prevent="previewClick(scope.row)" size="small">
预览
</el-button>
</template>
</el-table-column> -->
<el-table-column property="address" label="操作">
<template #default="scope">
<el-button @click.prevent="deletefileClick(scope.$index)"
size="small">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 底部按钮 -->
<template #footer>
<span class="dialog-footer">
<el-button @click="cancelSubmit">取 消</el-button>
<el-button type="primary" @click="submitClick" >确认上传</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
import { apifileupload } from '@/js/fileUpload/fileUpload.js'
import commFunction from '@/common/js/commFunction.js'
export default {
data () {
return {
gridData: [],
dialogFormVisible: false,
loading: false
}
},
methods: {
// 打开上传的控件
openaddattachments () {
this.dialogFormVisible = true
},
// 选择文件上传
handleChange (file, wrap) {
const uploadFile = file.target.files[0]
const fileSize = uploadFile.size / 1024
// const fileSize = uploadFile.size / 1024 / 1024
const fileName = file.target.files[0].name
this.transferImgToBase64(uploadFile, res => {
const localobjfile = {
name: fileName,
localsize: fileSize,
localurl: res
}
this.gridData.push(localobjfile)
// this.$refs.uploadInput.value = ''
})
},
// base64转换
transferImgToBase64 (files, cb) {
// 先判断浏览器是否支持,一般都支持
if (typeof FileReader === 'undefined') {
alert('您的浏览器不支持图片上传,请升级您的浏览器')
return false
}
// 实例化实例化`FileReader`对象
const reader = new FileReader()
// 读取内容
reader.readAsDataURL(files)
// 通过onload事件拿到文件,并注册一个回调事件cb,这个回调事件就是拿来上传文件、预览文件等等的操作,回调的参数就是处理好的base64格式文件
reader.onload = e => {
// eslint-disable-next-line no-unused-expressions
cb ? cb(e.target.result) : null
}
},
// 文件预览
previewClick (row) {
var string = row.localurl
var iframe = "<iframe width='100%' height='100%' :title='" + row.name + "' src='" + string + "'></iframe>"
var x = window.open()
x.document.open()
x.document.write(iframe)
x.document.close()
x.document.title = row.name
},
// 删除附件
deletefileClick (index) {
this.gridData.splice(index, 1)
},
// 取消上传
cancelSubmit () {
this.loading = false
this.dialogFormVisible = false
this.$refs.uploadInput.value = ''
this.gridData = []
},
// 确认上传
submitClick () {
this.loading = true
const arrfilelist = []
if (this.gridData && this.gridData.length > 0) {
this.gridData.forEach((item) => {
const dataBase64res = item.localurl.substring(item.localurl.indexOf(',') + 1)
const obj = {
operatID: 'I',
context_Str: dataBase64res,
accessoryName: item.name,
localFilePath: item.name,
ADAccessoryID: ''
}
arrfilelist.push(obj)
})
apifileupload(arrfilelist)
.then((res) => {
this.loading = false
const arrList = res.data.result.resultObj
if (arrList && arrList.length > 0) {
const newarr = this.concatarrfileFun(arrfilelist, arrList)
this.$emit('getattachmentList', newarr)
this.dialogFormVisible = false
this.$refs.uploadInput.value = ''
this.gridData = []
this.$message.success('附件上传成功!')
} else {
this.$message.error('附件上传失败!')
}
})
.catch((err) => {
this.$message.error('附件上传失败:' + err)
this.loading = false
})
} else {
this.$message.warning('请上传附件')
}
},
// 重组数据
concatarrfileFun (oldarr, newarr) {
const concatarr = []
oldarr.forEach((olditem) => {
newarr.forEach((newitem) => {
if (olditem.localFilePath === newitem.fileName) {
const obj = {
operatID: 'I',
context_Str: olditem.context_Str,
accessoryName: newitem.accessoryName,
localFilePath: newitem.fileName,
ADAccessoryID: newitem.ADAccessoryID,
url: newitem.url,
fileName: newitem.fileName,
downloadUrl: newitem.downloadUrl
}
concatarr.push(obj)
}
})
})
return concatarr
},
// 保留两位小数的大小
formatMoney (size) {
return commFunction.formatMoney(size)
}
}
}
</script>
<style lang="scss" scoped>
.addAttachments{
/deep/ .el-dialog__header,
/deep/ .el-dialog__body{
text-align: left !important;
}
.upload-wrap {
width: 80px;
position: relative;
border-radius: 5px;
overflow: hidden;
background-color: #fff;
transition: all 0.5s ease-in-out;
margin: 0 5px 5px 0;
.input,
.uploader-icon {
position: absolute;
z-index: 99;
width: 100%;
height: 100%;
}
.input {
opacity: 0;
cursor: pointer;
}
}
}
</style>
-
父组件使用:
-
引入
import addAttachments from '@/components/addAttachments/addAttachments.vue' import { apideleteAccessory } from '@/js/fileUpload/fileUpload.js'
-
注册:
components: { addAttachments },
-
使用:
<add-attachments ref="refaddattachments" @getattachmentList="getattachmentList"></add-attachments>
-
父组件通过refs打开子组件,并且进行数据的获取等
// 添加附件
uploadfileclick () {
this.$refs.refaddattachments.openaddattachments()
},
// 获取数据
getattachmentList (arrlist) {
if (arrlist && arrlist.length > 0) {
this.attachmentList = this.attachmentList.concat(arrlist)
} else {
this.attachmentList = []
}
},
// 查看附件
seefileClick (item) {
window.open(item.url)
},
// 删除附件
deletefileClick (item, index) {
this.$confirm('是否确定删除?删除即将从数据库中删除!', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
apideleteAccessory(item.ADAccessoryID)
.then((res) => {
const result = res.data.result.resultObj
if (result && result.length > 0) {
if (result[0].flag === 'Y') {
// this.applyBillInfo.ADAccessory.splice(index, 1)
this.attachmentList.splice(index, 1)
this.applyBillInfo.ADAccessory = []
this.$message.success('删除附件成功!')
} else {
this.$message.error('删除附件失败!')
}
}
})
.catch((err) => {
this.$message.error('删除附件失败:' + err)
})
})
},
// 下载附件
downfileClick (item) {
window.open(item.downloadUrl)
}
- 父组件的容器和触发方式
-
<div class="accessory-content"> <div class="content-title"> <div class="title-left"> 附件 </div> <div v-if="isHeaderEditable" class="title-right" ref="upLoadFile" :class="isHeaderEditable== false?'isNoEdit':''" @click="uploadfileclick">添加 </div> <div v-else class="title-right" ref="upLoadFile" :class="isHeaderEditable== false?'isNoEdit':''">添加</div> </div> <div class="content-main" v-if="attachmentList && attachmentList.length > 0"> <div class="content-attachment-list" v-for="(item, index) in attachmentList" :key="index + item"> <div class="attachment-list-name" @click.prevent="seefileClick(item)">{{item.fileName}}</div> <div class="attachment-list-right"> <div class="attachment-list-btn" @click.prevent="downfileClick(item)" > <i class="el-icon-download"></i> </div> <div class="attachment-list-btn" @click.prevent="deletefileClick(item,index)"> <i class="el-icon-delete"></i> </div> </div> </div> </div> </div>
-
- 父组件容器的样式
// 附件
.accessory-content{
display: flex;
flex-direction: column;
justify-content: flex-start;
background:#F3F8FC;
padding: 11px 14px;
box-sizing: border-box;
.content-title{
display: flex;
justify-content: space-between;
margin-bottom: 10px;
.title-left{
color: #303133;
font-size: 14px;
font-family: PingFangSC-Medium;
}
.title-right{
cursor: pointer;
color: rgba(0, 137, 255, 100);
font-size: 14px;
font-family: PingFangSC-Regular;
}
}
.content-main{
width: 100%;
.content-attachment-list{
display: flex;
justify-content: space-between;
align-items: center;
height: 30px;
line-height: 30px;
.attachment-list-name{
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
width: 80%;
text-align: left;
color: rgba(96, 98, 102, 100);
font-size: 14px;
font-family: PingFangSC-Regular;
cursor: pointer;
}
.attachment-list-right{
display: flex;
.attachment-list-btn{
cursor: pointer;
margin-right: 5px;
.el-icon-delete,
.el-icon-download{
width: 20px;
text-align: center;
font-size: 16px;
color: #0089FF;
}
}
}
}
}
}
最后的效果图
更多推荐
所有评论(0)