Vue+antd 上传附件a-upload组件化,附送C#异步上传文件代码【NetFrm4.5+】+Vue 增删改查代码
分类:
IT文章
•
2022-05-12 21:22:16
十年河东,十年河西,莫欺少年穷
学无止境,精益求精
这是一个后端开发人员的倔强
因项目需要,我从一个纯后端变成了前端+后端,也俗称全栈。
在实际项目中,上传附件几乎是必不可少的,因此,我们有必要将上传控件进行组件化。
设计理念,通过vue的父子传值进行封装,上传组件为子组件,调用方为父组件,由父组件传值给子组件,用来校验上传的文件扩展名及大小。
子组件
<template>
<a-upload
:beforeUpload="beforeUpload"
:multiple="false"
@change="filechange"
:customRequest="customRequest"
:fileList="fileList"
:remove="fileRemove"
>
<a-button> <a-icon type="upload" /> 选择文件 </a-button>
</a-upload>
</template>
<script>
export default {
props: ["fileinfo"],
created() {},
data() {
return {
fileList: [],
};
},
methods: {
beforeUpload(file) {
var that = this;
//console.log(file);
return new Promise((resolve, reject) => {
const isLt100M = file.size / 1024 / 1024 > that.fileinfo.maxsize;
if (isLt100M) {
this.$message.warning(
"上传附件大小不能超过" + that.fileinfo.maxsize + "M。"
);
return reject(false);
}
var index = file.name.lastIndexOf(".");
var suffix = file.name.substring(index + 1);
if( that.fileinfo.filetype.indexOf(suffix)<0){
this.$message.warning(
"上传的文件格式不符合要求"
);
return reject(false);
}
return resolve(true);
});
},
filechange(info) {
//console.log(info);
this.fileList = info.fileList;
//console.log(this.fileList);
if (info.file.status == "uploading") {
}
if (info.file.status === "done") {
} else if (info.file.status === "error") {
}
},
customRequest(data) {
// 上传提交
const formData = new FormData();
formData.append("file", data.file);
this.saveFile(formData);
},
saveFile(formData) {
let that = this;
this.$axios({
url: "/api/File/UploadFileStream",
method: "post",
data: formData,
})
.then(function (result) {
//console.log(result);
//that.fileList.push(result.Data)
if (result.IsSuccess) {
for (var i = 0; i < that.fileList.length; i++) {
that.fileList[i].status = "done";
}
console.log(that.fileinfo.uploadfiles);
that.fileinfo.uploadfiles.push(result.Data);
that.$message.success("上传附件成功。");
} else {
//that.fileList = [];
for (var i = 0; i < that.fileList.length; i++) {
if (that.fileList[i].status != "done") {
that.fileList.splice(i, 1);
}
}
that.$message.warning(result.ResultMessage);
}
})
.catch(function (error) {
console.log(error);
});
},
fileRemove(file) {
//console.log(file);
var that = this;
for (var i = 0; i < that.fileinfo.uploadfiles.length; i++) {
if (
that.fileinfo.uploadfiles[i].oldfilename == file.name &&
that.fileinfo.uploadfiles[i].filesize == file.size
) {
that.fileinfo.uploadfiles.splice(i, 1);
//alert(1)
}
}
},
},
};
</script>
View Code
父组件
<template>
<div>
<a-row align="middle" class="arowLat">
<a-col :span="12">
<a-checkable-tag v-model="checked" @change="handleChange">
OTA固件包
</a-checkable-tag>
<file-upload v-bind:fileinfo="fileinfo"></file-upload>
</a-col>
<a-col :span="12">
<a-button @click="submit">提交</a-button>
</a-col>
</a-row>
</div>
</template>
<script>
export default {
name: "Echarts",
data() {
return {
checked:false,
fileinfo: {
maxsize: 1024 * 1024 * 100,
filetype: ["jpg", "png"],
uploadfiles: [],
},
};
},
methods: {
submit() {
console.log(this.fileinfo.uploadfiles);
}
},
mounted() {},
};
</script>
<style scoped>
.img {
100%;
height: auto;
}
.arow {
text-align: left;
}
.arowLat {
text-align: left;
margin-top: 25px;
}
</style>
View Code
下面来简单分析下上述源码
父组件Data中fileinfo的属性用来校验文件大小,扩展名
data() {
return {
checked:false,
fileinfo: {
maxsize: 1024 * 1024 * 100,
filetype: ["jpg", "png"],
uploadfiles: [],
},
};
}
注:uploadfiles 用于接收子组件请求后台的结果,我的后台返回值为:
{
Data {
LocalFilePath: "E:IOTIotApiContentOTA4dccdff9bc17413c96d98031a8a451ec.bin",
filedata: [80, 19, 0, 32, 1, 33, 0, 8, 1, 139, 0, 8, 69, 114, 0, 8, 229, 138, 0, 8, 43, 74, 0, 8, 219, 182, 0, 8, 0, 0...],
filename: "4dccdff9bc17413c96d98031a8a451ec.bin",
filepath: "~/Content/OTA/4dccdff9bc17413c96d98031a8a451ec.bin",
filesize: 49336,
oldfilename: "LBS-1522-YQ4501.jpg",
}
IsSuccess: true,
ResultCode: 0,
ResultMessage: "请求成功...",
}
fileinfo 用于传值给子组件,子组件中有对应的 props,如下
a-upload 组件中有个名叫 beforeUpload 的钩子函数,我们用来校验上传的文件,如果通过校验,则上传
beforeUpload(file) {
var that = this;
//console.log(file);
return new Promise((resolve, reject) => {
const isLt100M = file.size / 1024 / 1024 > that.fileinfo.maxsize;
if (isLt100M) {
this.$message.warning(
"上传附件大小不能超过" + that.fileinfo.maxsize + "M。"
);
return reject(false);
}
var index = file.name.lastIndexOf(".");
var suffix = file.name.substring(index + 1);
if( that.fileinfo.filetype.indexOf(suffix)<0){
this.$message.warning(
"上传的文件格式不符合要求"
);
return reject(false);
}
return resolve(true);
});
},
fileRemove 方法用来同步移除 uploadfiles 的元素,保持和组件显示的上传文件一致。
fileRemove(file) {
//console.log(file);
var that = this;
for (var i = 0; i < that.fileinfo.uploadfiles.length; i++) {
if (
that.fileinfo.uploadfiles[i].oldfilename == file.name &&
that.fileinfo.uploadfiles[i].filesize == file.size
) {
that.fileinfo.uploadfiles.splice(i, 1);
//alert(1)
}
}
},
在组件开发阶段,遇到一个问题,上传成功后,上传的状态一直是 uploading ,为了解决这个问题,我们需要在 filechange、customRequest、saveFile 一起解决。
主要是在 filechange 中给filelist赋值,在 saveFile 中当文件上传成功后,修改状态为done,如果上传失败,我们需要将filelist中上传失败的元素移除。
filechange(info) {
//console.log(info);
this.fileList = info.fileList;
//console.log(this.fileList);
if (info.file.status == "uploading") {
}
if (info.file.status === "done") {
} else if (info.file.status === "error") {
}
},
customRequest(data) {
// 上传提交
const formData = new FormData();
formData.append("file", data.file);
this.saveFile(formData);
},
saveFile(formData) {
let that = this;
this.$axios({
url: "/api/File/UploadFileStream",
method: "post",
data: formData,
})
.then(function (result) {
//console.log(result);
//that.fileList.push(result.Data)
if (result.IsSuccess) {
for (var i = 0; i < that.fileList.length; i++) {
that.fileList[i].status = "done";
}
console.log(that.fileinfo.uploadfiles);
that.fileinfo.uploadfiles.push(result.Data);
that.$message.success("上传附件成功。");
} else {
//that.fileList = [];
for (var i = 0; i < that.fileList.length; i++) {
if (that.fileList[i].status != "done") {
that.fileList.splice(i, 1);
}
}
that.$message.warning(result.ResultMessage);
}
})
.catch(function (error) {
console.log(error);
});
},
View Code
<template>
<div>
<a-card
hoverable="true"
title=""
headStyle="text-align:left;color:#606266;font-size:14px"
bodyStyle="border:none"
>
<a slot="extra" href="#" style="float: left">
<a-breadcrumb separator=">">
<a-breadcrumb-item>OTA升级</a-breadcrumb-item>
<a-breadcrumb-item>电池OTA升级 </a-breadcrumb-item>
</a-breadcrumb>
</a>
<div>
<a-row align="middle" class="arow">
<a-col :span="6">
<a-checkable-tag v-model="checked" @change="handleChange">
OTA版本号
</a-checkable-tag>
<a-input
placeholder="请输入OTA版本号"
style=" 180px"
v-model="SearchInfo.SoftWare"
/>
</a-col>
<a-col :span="6">
<a-checkable-tag v-model="checked" @change="handleChange">
BMS版本号
</a-checkable-tag>
<a-input
placeholder="请输入BMS版本号"
style=" 180px"
v-model="SearchInfo.OldSoftWare"
/>
</a-col>
<a-col :span="6"> </a-col>
<a-col :span="6">
<a-button type="primary" @click="Search"> 查询 </a-button>
<a-button type="danger" @click="() => setModal1Visible(true)">
新增
</a-button>
</a-col>
</a-row>
<a-table
:columns="columns"
:data-source="data"
style="margin-top: 20px"
>
<template slot="action" slot-scope="text, record">
<a slot="action" href="javascript:;" @click="deleterow(record)"
>删除</a
>
<a slot="action" href="javascript:;" @click="onEdit(record)" >编辑</a>
<!-- <span slot="action" slot-scope="text" href="javascript:;" @click="onEdit()" >删除</span> -->
</template>
</a-table>
</div>
</a-card>
<a-modal
title="新增OTA升级信息"
:width="760"
:okText="提交"
:cancelText="取消"
:dialog-style="{ top: '20px' }"
:visible="modal1Visible"
@ok="() => Save()"
@cancel="() => setModal1Visible(false)"
>
<a-card
hoverable="true"
title=""
headStyle="text-align:left;color:#606266;font-size:14px"
bodyStyle="border:none"
>
<a-row align="middle" class="arow">
<a-col :span="12">
<a-checkable-tag v-model="checked" @change="handleChange">
OTA版本号
</a-checkable-tag>
<a-input
placeholder="请输入OTA版本号"
style=" 180px"
v-model="OtaModel.SoftWare"
/>
</a-col>
<a-col :span="12">
<a-checkable-tag v-model="checked" @change="handleChange">
单包大小
</a-checkable-tag>
<a-input-number
v-model="OtaModel.SigPackSize"
placeholder="请输入单包大小"
:min="64"
:max="2048"
style=" 180px"
/>
</a-col>
</a-row>
<a-row align="middle" class="arowLat">
<a-col :span="12">
<a-checkable-tag v-model="checked" @change="handleChange">
BMS版本号
</a-checkable-tag>
<a-input
placeholder="请输入BMS版本号"
style=" 180px"
v-model="OtaModel.OldSoftWare"
/>
</a-col>
<a-col :span="12">
<a-checkable-tag v-model="checked" @change="handleChange">
升级描述
</a-checkable-tag>
<a-input
placeholder="请输入升级描述"
style=" 180px"
v-model="OtaModel.OtaFileInfo"
/>
</a-col>
</a-row>
<a-row align="middle" class="arowLat">
<a-col :span="12">
<a-checkable-tag v-model="checked" @change="handleChange">
OTA固件包
</a-checkable-tag>
<file-upload v-bind:fileinfo="fileinfo"></file-upload>
</a-col>
<a-col :span="12"> </a-col>
</a-row>
</a-card>
</a-modal>
</div>
</template>
<script>
import moment from "moment";
import "moment/locale/zh-cn";
import locale from "ant-design-vue/es/date-picker/locale/zh_CN";
const formatterTime = (val) => {
alert(val);
return val ? moment(val).format("YYYY-MM-DD HH:mm:ss") : "";
};
const columns = [
{
title: "升级描述",
200,
dataIndex: "OtaFileInfo",
key: "OtaFileInfo",
align: "center",
},
{ title: "固件大小(字节)", dataIndex: "FileSize", key: "1", align: "center" },
{ title: "BMS版本号", dataIndex: "OldSoftWare", key: "2", align: "center" },
{ title: "OTA版本号", dataIndex: "SoftWare", key: "3", align: "center" },
{
title: "单包大小(字节)",
dataIndex: "SigPackSize",
key: "4",
align: "center",
},
{
title: "创建日期",
dataIndex: "CreateTime",
key: "8",
align: "center",
customRender: function (val) {
return val ? moment(val).format("YYYY-MM-DD") : "";
},
},
{
title: "操作",
key: "operation",
align: "center",
100,
scopedSlots: { customRender: "action"},
},
];
const data = [];
export default {
name: "Echarts",
data() {
return {
locale,
checked: false,
checkedmodal: true,
dateFormat: "YYYY/MM/DD",
monthFormat: "YYYY/MM",
data,
columns,
modal1Visible: false,
fileinfo: {
maxsize: 1024 * 1024 * 10,
filetype: ["bin"],
uploadfiles: [],
},
OtaModel: {
OldSoftWare: "",
SoftWare: "",
SigPackSize: 512,
OtaFileInfo: "",
FileName: "",
oldfilename: "",
LocalFilePath: "",
filesize: 0,
filedata: [],
FilePath: "",
},
SearchInfo: {
SoftWare: "",
OldSoftWare: "",
PageNumber: 1,
PageSize: 1,
Stime: "2020-01-01",
Etime: "2030-01-01",
},
};
},
methods: {
moment,
onChange(dates, dateStrings) {
console.log("From: ", dates[0], ", to: ", dates[1]);
console.log("From: ", dateStrings[0], ", to: ", dateStrings[1]);
},
handleChange(checked) {},
setModal1Visible(modal1Visible) {
this.modal1Visible = modal1Visible;
},
Save() {
let that = this;
if (!that.OtaModel.OldSoftWare) {
that.$message.error("请输入BMS版本号。");
return;
} else if (!that.OtaModel.SoftWare) {
that.$message.error("请输入OTA版本号。");
return;
} else if (!that.OtaModel.SigPackSize) {
that.$message.error("请输入单包大小。");
return;
} else if (!that.OtaModel.OtaFileInfo) {
that.$message.error("请输入OTA版本描述");
return;
} else if (
!that.fileinfo.uploadfiles ||
that.fileinfo.uploadfiles.length != 1
) {
that.$message.error("请上传升级固件包【有且仅能上传一个固件包】");
return;
} else {
that.OtaModel.FileName = that.fileinfo.uploadfiles[0].filename;
that.OtaModel.oldfilename = that.fileinfo.uploadfiles[0].oldfilename;
that.OtaModel.LocalFilePath =
that.fileinfo.uploadfiles[0].LocalFilePath;
that.OtaModel.filesize = that.fileinfo.uploadfiles[0].filesize;
that.OtaModel.filedata = that.fileinfo.uploadfiles[0].filedata;
that.OtaModel.FilePath = that.fileinfo.uploadfiles[0].filepath;
//console.log(that.OtaModel);
that
.$axios({
url: "/api/BatteryOta/CreateBatteryOtaSoftWareInfo",
method: "post",
data: that.OtaModel,
})
.then(function (result) {
if (result.IsSuccess) {
that.OtaModel = {
OldSoftWare: "",
SoftWare: "",
SigPackSize: 512,
OtaFileInfo: "",
FileName: "",
oldfilename: "",
LocalFilePath: "",
filesize: 0,
filedata: [],
FilePath: "",
};
that.modal1Visible = false;
} else {
that.$message.error(result.ResultMessage);
that.OtaModel = {
OldSoftWare: "",
SoftWare: "",
SigPackSize: 512,
OtaFileInfo: "",
FileName: "",
oldfilename: "",
LocalFilePath: "",
filesize: 0,
filedata: [],
FilePath: "",
};
}
})
.catch(function (error) {
console.log(error);
});
}
},
Search() {
let that = this;
that
.$axios({
url: "/api/BatteryOta/SearchOtaSoftWareInfo",
method: "post",
data: that.SearchInfo,
})
.then(function (result) {
console.log(result);
if (result.IsSuccess) {
that.data = result.Data.Data;
} else {
that.$message.error(result.ResultMessage);
}
})
.catch(function (error) {
console.log(error);
});
},
deleterow(record) {
console.log(record);
},
},
mounted() {},
created() {
this.Search();
},
};
</script>
<style scoped>
.img {
100%;
height: auto;
}
.arow {
text-align: left;
}
.arowLat {
text-align: left;
margin-top: 25px;
}
</style>