一.前言项目中使用到比较多的关于excel的前端与下载,整理出来,以便后续使用或分析他人。
1.前端vue:模板下载与导入excel
导入excel封装了子组件,点击导入按钮可调用子组件,打开文件上传的对话框,上传成功后返回结果
class="pull-right"
icon="el-icon-upload"
type="primary"
size="mini"
@click="importfile()"
>批量导入
class="pull-right right-10"
icon="el-icon-download"
type="primary"
size="mini"
@click="downloadfile('档案模板')"
>模板下载
size="mini"
type="primary"
icon="el-icon-plus"
class="pull-right"
@click="addrow"
>新增
placeholder="请输入编码,名称"
prefix-icon="el-icon-search"
v-model="finqueryparams.archivefilter"
size="mini"
>
:apiurl="fileuploadurl"
ref="reffileupload"
:refresh="refresh"
:otherparams="{brandid: queryparams.brandid}"
>
importfile() {
this.$refs.reffileupload.open();
}
向后台提交文件的方法
submitfile() {
const _this = this;
if (!_this.files.name) {
_this.$message.warning("请选择要上传的文件!");
return false;
}
let fileformdata = new formdata();
//filename是键,file是值,就是要传的文件
fileformdata.append("file", _this.files, _this.files.name);
if(_this.otherparams){
const keys=object.keys(_this.otherparams);
keys.foreach(e=>{
fileformdata.append(e, _this.otherparams[e]);
})
}
let requestconfig = {
headers: {
"content-type": "multipart/form-data"
}
};
ajaxhelper.post(_this.apiurl, fileformdata, requestconfig)
.then(res => {
console.log(res);
if (res.success) {
const result = res.result;
if (result.errorcount == && result.successcount > ) {
_this.$message({
message: `导入成功,成功${result.successcount}条`,
type: "success"
});
_this.closefileupload();
_this.refresh();
} else if (result.errorcount > && result.successcount >= ) {
_this.refresh();
_this.tabledata = result.uploaderrors;
_this.successcount = result.successcount;
_this.innervisible = true;
} else if (result.errorcount == && result.successcount == ) {
_this.$message({
message: `上传文件中数据为空`,
type: "error"
});
}
}
})
.catch(function(error) {
console.log(error);
});
},
这是上传文件的调用方法。
2.模板下载
关于模板下载,之前没有考虑到ie10浏览器的兼容问题,导致在ie10下文件没法下载,后来百度后找到了解决办法。
downloadfile(name) {
let requestconfig = {
headers: {
"content-type": "application/json;application/octet-stream"
}
};
ajaxhelper.post(this.downloadurl, requestconfig, {
responsetype: "blob"
}).then(res => {
// 处理返回的文件流
const content = res.data;
const blob = new blob([content]);
var date =
new date().getfullyear()
""
(new date().getmonth() 1)
""
new date().getdate();
const filename = date name ".xlsx";
if ("download" in document.createelement("a")) {
// 非ie下载
const elink = document.createelement("a");
elink.download = filename;
elink.style.display = "none";
elink.href = url.createobject;
document.body.appendchild(elink);
elink.click();
url.revokeobject; // 释放url 对象
document.body.removechild(elink);
} else {
// ie10 下载
navigator.mssaveblob(blob, filename);
}
});
},
前端的处理就结束了。
3.后端对于文件上传和下载的处理
文件上传
public uploadresult uploadfiles(iformfile file, guid brandid)
{
try
{
uploadresult uploadresult = new uploadresult();
if (file == null)
{
throw new userfriendlyexception(, "上传的文件为空,请重新上传");
}
string filename = path.getfilename(file.filename);
string fileex = path.getextension(filename);//获取上传文件的扩展名
string nofilename = path.getfilenamewithoutextension(filename);//获取无扩展名的文件名
string filetype = ".xls,.xlsx";//定义上传文件的类型字符串
if (!filetype.contains(fileex))
{
throw new userfriendlyexception(, "无效的文件类型,只支持.xls和.xlsx文件");
}
//源数据
memorystream mssource = new memorystream();
file.copyto(mssource);
mssource.seek(, seekorigin.begin);
datatable sourceexcel = readstreamtodatatable(mssource, "", true); //模板数据
string datadir = _hosting.webrootpath;//获得当前服务器程序的运行目录
datadir = path.combine(datadir, "exceltemplate");
var path = datadir "//档案模版.xlsx";
memorystream msmodel = new memorystream();
filestream stream = new filestream(path, filemode.open);
stream.copyto(msmodel);
msmodel.seek(, seekorigin.begin);
datatable templateexcel = readstreamtodatatable(stream, "", true);
//验证是否同模板相同
string columnname = templateexcel.columns[].columnname;
if (columnname != sourceexcel.columns[].columnname)
{
throw new userfriendlyexception(, "上传的模板文件不正确");
}
int sucesscount = ;
int errorcount = ;
// 处理后台逻辑 执行 插入操作 uploadresult.successcount = sucesscount;
uploadresult.errorcount = errorcount;
uploadresult.uploaderrors = errorlist;
return uploadresult;
}
catch (exception ex)
{
throw new userfriendlyexception(, "上传的模板文件不正确");
}
}
将文件流转化为datable
public static datatable readstreamtodatatable(stream filestream, string sheetname = null, bool isfirstrowcolumn = true)
{
//定义要返回的datatable对象
datatable data = new datatable();
//excel工作表
isheet sheet = null;
//数据开始行(排除标题行)
int startrow = ;
try
{
//根据文件流创建excel数据结构,npoi的工厂类workbookfactory会自动识别excel版本,创建出不同的excel数据结构
iworkbook workbook = workbookfactory.create(filestream);
//如果有指定工作表名称
if (!string.isnullorempty(sheetname))
{
sheet = workbook.getsheet(sheetname);
//如果没有找到指定的sheetname对应的sheet,则尝试获取第一个sheet
if (sheet == null)
{
sheet = workbook.getsheetat();
}
}
else
{
//如果没有指定的sheetname,则尝试获取第一个sheet
sheet = workbook.getsheetat();
}
if (sheet != null)
{
irow firstrow = sheet.getrow();
//一行最后一个cell的编号 即总的列数
int cellcount = firstrow.lastcellnum;
//如果第一行是标题列名
if (isfirstrowcolumn)
{
for (int i = firstrow.firstcellnum; i < cellcount; i)
{
icell cell = firstrow.getcell(i);
if (cell != null)
{
string cellvalue = cell.stringcellvalue;
if (cellvalue != null)
{
datacolumn column = new datacolumn(cellvalue);
data.columns.add(column);
}
}
}
startrow = sheet.firstrownum ;
}
else
{
startrow = sheet.firstrownum;
}
//最后一列的标号
int rowcount = sheet.lastrownum;
for (int i = startrow; i <= rowcount; i)
{
irow row = sheet.getrow(i);
if (row == null || row.firstcellnum < ) continue; //没有数据的行默认是null datarow datarow = data.newrow();
for (int j = row.firstcellnum; j < cellcount; j)
{
//同理,没有数据的单元格都默认是null
icell cell = row.getcell(j);
if (cell != null)
{
if (cell.celltype == celltype.numeric)
{
//判断是否日期类型
if (dateutil.iscelldateformatted(cell))
{
datarow[j] = row.getcell(j).datecellvalue;
}
else
{
datarow[j] = row.getcell(j).tostring().trim();
}
}
else
{
datarow[j] = row.getcell(j).tostring().trim();
}
}
}
data.rows.add(datarow);
}
}
return data;
}
catch (exception ex)
{
throw ex;
} }
文件下载比较简单
public async taskdownloadfiles()
{
string datadir = _hosting.webrootpath;//获得当前服务器程序的运行目录
datadir = path.combine(datadir, "exceltemplate");
var path = datadir "//档案模版.xlsx";
var memorystream = new memorystream();
using (var stream = new filestream(path, filemode.open))
{
await stream.copytoasync(memorystream);
}
memorystream.seek(, seekorigin.begin);
return new filestreamresult(memorystream, "application/octet-stream");//文件流方式,指定文件流对应的contentype。
}
文件上传结果通知类
public class uploadresult
{
public int repeatcount { get; set; }
public int successcount { get; set; }
public int filerepeatcount { get; set; }
public int errorcount { get; set; } public listuploaderrors { get; set; }
}
public class uploaderrordto
{
public string rowindex { get; set; }
public string errorcol { get; set; }
public string errordata { get; set; }
}
通过以上处理后,我们就可以在前端实现文件的上传了,若上传失败则会返回失败结果
以上就是整个前后端关于文件上传与下载的实现,想通过日常记录这种方式,来帮助自己更好的掌握基础,稳固自己的技能