在开发的过程中,上传文件或者导入数据是一件很常见的事情,导入数据可以有两种方式:

  1. 前端上传文件到后台,后台读取文件内容,进行验证再进行存储
  2. 前端读取数据,进行数据验证,然后发送数据到后台进行存储

这两种方式需要根据不同的业务才进行采用

这次用.Net6.0+Vue3来实现一个数据导入的功能

接下来分别用代码来实现这两种方式

1. 前端上传文件到后台进行数据存储

1.1编写文件上传接口

        [DisableRequestSizeLimit]
[HttpPost]
public IActionResult Upload()
{
var files = Request.Form.Files;
long size = files.Sum(f => f.Length); string contentRootPath = AppContext.BaseDirectory;
List<string> filenames = new List<string>();
foreach (IFormFile formFile in files)
{
if (formFile.Length > 0)
{
string fileExt = Path.GetExtension(formFile.FileName);
long fileSize = formFile.Length;
string newFileName = System.Guid.NewGuid().ToString() + fileExt;
var filePath = contentRootPath + "/fileUpload/";
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
using (var stream = new FileStream(filePath + newFileName, FileMode.Create))
{
formFile.CopyTo(stream);
}
filenames.Add(newFileName);
}
}
return Ok(filenames);
}

这里只是上传文件分了两步走,第一步把文件上传到服务器,第二步调用接口把返回的文件路径发送给后台进行数据保存

1.2存储上传文件路径,读取数据并进行存储

  /// <summary>
/// 上传文件数据
/// </summary>
/// <param name="uploadStuInfoInput"></param>
/// <returns></returns>
[HttpPut]
public IActionResult Put(DataInput uploadStuInfoInput)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fileUpload", uploadStuInfoInput.filePath);
if (!System.IO.File.Exists(filePath))
{
return BadRequest("导入失败,文件不存在!");
}
var row = MiniExcelLibs.MiniExcel.Query<CompanyImportInput>(filePath).ToList();
companies.AddRange(row.Select(x => new Company { Name = x.名称, Address = x.地址 }));
return Ok("导入成功!");
}

1.3前端Vue建立创建列表数据页面,包含表格功能及分页功能

<el-table :data="state.tableData.data">
      <el-table-column v-for="item in state.colunm" :prop="item.key" :key="item.key" :label="item.lable">
      </el-table-column>
    </el-table>
 <div class='block flex justify-end' v-if='state.tableData.total > 0'>
      <el-pagination v-model:currentPage="state.searchInput.PageIndex" v-model:page-size="state.searchInput.PageSize"
        :page-sizes="[10, 50, 200, 1000]" layout="total, sizes, prev, pager, next, jumper" @size-change="getData"
        @current-change="getData" :total="state.tableData.total" />
    </div>

1.4调用接口获取表格数据方法

 const getData = () => {
      axios.get('/Company', { params: state.searchInput }).then(function (response) {
        state.tableData = response.data;
      })
    }

1.5后台开发数据返回接口

        [HttpGet]
public dynamic Get([FromQuery] SelectInput selectInput)
{
return new
{
total = companies.Count(),
data = companies.Skip((selectInput.pageIndex - 1) * selectInput.pageSize).Take(selectInput.pageSize).ToList()
};
}

1.6主页面创建上传文件组件并进行引用

import FileUpload from '@/components/FileUpload.vue'; 

并绑定子页面回调方法fileUploadchildClick

  <FileUpload ref="fileUpload" @childClick="fileUploadchildClick" accept=".xlsx" title="上传文件"></FileUpload>

1.7FleUpload页面主要上传文件到服务器,并回调父页面存储接口

 <el-dialog :close-on-click-modal="false" v-model="state.dialogVisible" :title="title" width="40%">
    <el-form :model='state.formData' label-width='130px' class='dialogForm'>
      <el-upload class='upload-demo' :limit="1" drag :accept='accept' :file-list='state.fileList' :show-file-list='true'
        :on-success='fileUploadEnd' :action='fileUploadUrl()'>
        <i class='el-icon-upload'></i>
        <div class='el-upload__text'>将文件拖到此处,或<em>点击上传</em></div>
        <div class='el-upload__tip'>请选择({{  accept  }})文件</div>
      </el-upload>
      <div>
        <el-form-item>
          <el-button type='primary' @click='submit'>导入</el-button>
          <el-button @click='cancel'>取消</el-button>
        </el-form-item>
      </div>
    </el-form>
  </el-dialog>

1.8这里的title,accept参数由父页面传值过来,可以进行组件复用

选择文件成功回调方法

 const fileUploadEnd = (response, file) => {
      state.fileresponse = file.name;
      state.formData.filePath = response[0];
      if (state.fileList.length > 0) {
        state.fileList.splice(0, 1);
      }
    }

1.9提交保存时回调父页面存储数据方法

const submit = () => {
      if (state.formData.filePath == '') {
        ElMessage.error('请选择上传的文件')
        return;
      }
      context.emit('childClick', state.formData)
    }

1.10父页面方法调用接口进行数据存储,存储成功后关闭子页面

 const fileUploadchildClick = (e) => {
      axios.put('/Company', {
        filePath: e.filePath,
      }).then(function (response) {
        if (response.status == 200) {
          ElMessage.success(response.data);
          fileUpload.value.cancel();
          getData();
        } else {
          ElMessage.error(response.data)
        }
      })
    }

1.11后台数据存储接口

 /// <summary>
/// 上传文件数据
/// </summary>
/// <param name="uploadStuInfoInput"></param>
/// <returns></returns>
[HttpPut]
public IActionResult Put(DataInput uploadStuInfoInput)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fileUpload", uploadStuInfoInput.filePath);
if (!System.IO.File.Exists(filePath))
{
return BadRequest("导入失败,文件不存在!");
}
var row = MiniExcelLibs.MiniExcel.Query<CompanyImportInput>(filePath).ToList();
companies.AddRange(row.Select(x => new Company { Name = x.名称, Address = x.地址 }));
return Ok("导入成功!");
     }

2前端读取数据,发送读取数据到后台进行数据存储

2.1创建上传数据组件并引用

import DataUpload from '@/components/DataUpload.vue';

并绑定子页面回调方法dataUploadchildClick

<DataUpload ref="dataUpload" @childClick="dataUploadchildClick" accept=".xlsx" title="上传数据"></DataUpload>

2.2DataUpload页面主要读取选择文件数据,并进行展示

<el-dialog :close-on-click-modal="false" v-model="state.dialogVisible" :title="title" width="50%">
    <el-upload class="upload-demo" :action='accept' drag :auto-upload="false" :on-change="uploadChange" :limit="1">
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
    </el-upload>
    <div>
      <el-form-item>
        <el-button @click='submit'>确认导入</el-button>
      </el-form-item>
    </div>
    <el-table :data="state.tableData.data">
      <el-table-column v-for="item in state.colunm" :prop="item.key" :key="item.key" :label="item.lable">
      </el-table-column>
    </el-table>
    <div class='block flex justify-end' v-if='state.tableData.total > 0'>
      <el-pagination v-model:currentPage="state.searchInput.PageIndex" v-model:page-size="state.searchInput.PageSize"
        :page-sizes="[10, 50, 200, 1000]" layout="total, sizes, prev, pager, next, jumper" @size-change="getData"
        @current-change="getData" :total="state.tableData.total" />
    </div>
  </el-dialog>

2.3文件上传成功方法,保存数据到临时变量进行分页处理

const uploadChange = async (file) => {
      let dataBinary = await readFile(file.raw)
      let workBook = XLSX.read(dataBinary, { type: 'binary', cellDates: true })
      let workSheet = workBook.Sheets[workBook.SheetNames[0]]
      let data: any = XLSX.utils.sheet_to_json(workSheet)       let tHeader = state.colunm.map(obj => obj.lable)
      let filterVal = state.colunm.map(obj => obj.key)
      tHeader.map(val => filterVal.map(obj => val[obj]))
      const tempData: any = [];
      data.forEach((value) => {
        const ob = {};
        tHeader.forEach((item, index) => {
          ob[filterVal[index]] = value[item].toString();
        })
        tempData.push(ob);
      })
      state.tempTableData = tempData;
      getData();
    }

2.4数据绑定到表格上,这里需要通过当前选择页码及页面显示数量处理需要绑定到表格上的数据

const getData = () => {
      const tempData: any = [];
      state.tempTableData.forEach((value, index) => {
        if (index >= ((state.searchInput.PageIndex - 1) * state.searchInput.PageSize) && index < ((state.searchInput.PageIndex) * state.searchInput.PageSize)) {
          tempData.push(value);
        }
      });
      state.tableData.data = tempData;
      state.tableData.total = state.tempTableData.length;
    }

2.5点击确认导入按钮回调父页面方法进行数据保存

const submit = () => {
      context.emit('childClick', state.tempTableData)
    }

2.6父页面方法调用接口进行数据存储,存储成功后关闭子页面

const dataUploadchildClick = (data) => {
      axios.post('/Company', data)
        .then(function (response) {
          if (response.status == 200) {
            ElMessage.success(response.data);
            dataUpload.value.cancel();
            getData();
          } else {
            ElMessage.error(response.data)
          }
        })
    }

2.7后台数据存储接口

  /// 上传数据
/// </summary>
/// <param name="uploadStuInfoInput"></param>
/// <returns></returns>
[HttpPost]
public IActionResult Post(List<Company> companiesInput)
{
companies.AddRange(companiesInput);
return Ok("保存成功!"); }

最后关于这个数据导入的功能就完成了,代码中有很多得伪代码,而且很多功能还待完善,后续再进行补充

附上git地址:https://gitee.com/wyf854861085/file-upload.git

Git演示图:

.Net+Vue3实现数据简易导入功能的更多相关文章

  1. [Django]数据批量导入

    前言:历经一个月的复习,考试终于结束了.这期间上班的时候有研究了Django网页制作过程中,如何将数据批量导入到数据库中. 这个过程真的是惨不忍睹,犯了很多的低级错误,这会在正文中说到的.再者导入数据 ...

  2. .Net之Nopi Excel数据导出和批量导入功能

    一.介绍NPOI和编写demo的原因 1.Npoi是什么: 它是一个专门用于读写Microsoft Office二进制和OOXML文件格式的.NET库,我们使用它能够轻松的实现对应数据的导入,导出功能 ...

  3. c#直接调用ssis包实现Sql Server的数据导入功能

    调用ssis包实现Sql Server的数据导入功能网上已经有很多人讨论过,自己参考后也动手实现了一下,上一次笔者的项目中还用了一下这个功能.思前想后,决定还是贴一下增强记忆,高手请54. 1.直接调 ...

  4. 解析大型.NET ERP系统 设计通用Microsoft Excel导入功能

    做企业管理软件很难避免与Microsoft Excel打交道,常常是软件做好了,客户要求说再做一个Excel导入功能.导入Excel数据的功能的难度不大,从Excel列数据栏位的取值,验证值,再导入到 ...

  5. 基于Metronic的Bootstrap开发框架经验总结(7)--数据的导入、导出及附件的查看处理

    在很多系统模块里面,我们可能都需要进行一定的数据交换处理,也就是数据的导入或者导出操作,这样的批量处理能给系统用户更好的操作体验,也提高了用户录入数据的效率.我在较早时期的EasyUI的Web框架上, ...

  6. 循序渐进开发WinForm项目(5)--Excel数据的导入导出操作

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

  7. 027医疗项目-模块二:药品目录的导入导出-导入功能的Action的编写

    前一篇文章我们写了Service层,这篇文章我们写一下Action层. 实现的功能: 1:我们先下载模板:然后按照模板里面的规则,插入数据.比如存在d盘. 2:然后浏览找到那个文件,上传上去. 然后把 ...

  8. 026医疗项目-模块二:药品目录的导入导出-导入功能的Service的编写

    这个导入功能要实现的效果是: 思路是: 因为我们最后是在Action层中调用的HxlsRead工具,这个工具传入的就是我们要实现的上一篇文章说到的实现了HxlsOptRowsInterface接口的类 ...

  9. php做EXCEL数据导出导入开发的一些小问题

    前两天刚刚做开发CRM系统项目,在做要做EXCEL导出导入功能,因为以前做.NET开发用的是NPOI,但可是没找到PHP版本的,所以就网搜找了个国外的开源PHPEXCEL , 一开始只是做了简单的导入 ...

随机推荐

  1. 3D还原货拉拉女孩身亡真相,这一环值得反思!

    货拉拉女孩跳车身亡的消息,让人惋惜又震惊.司机多次偏离原始路线,女孩最终选择跳车,结果不幸身亡. 货拉拉女孩跳车真相被3D还原 有人质疑平台监管不力,造成如此惨剧,有人吐槽企业压榨员工,司机绕路是不得 ...

  2. jdbc连接数据库问题

    ### Error querying database.  Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Fail ...

  3. leetcode二叉树题目总结

    leetcode二叉树题目总结 题目链接:https://leetcode-cn.com/leetbook/detail/data-structure-binary-tree/ 前序遍历(NLR) p ...

  4. go 编程规范

    如果没有编程规范会有什么问题? 哪些地方可以需要指定规范? 非编码类规范:编码规范 非编码规范 开源规范 http://www.ruanyifeng.com/blog/2011/05/how_to_c ...

  5. C语言-直接排序

    #include<stdio.h> #define MAXSIZE 100 typedef int KeyType; typedef struct { KeyType key; }Reco ...

  6. java.Scanner 拓展用法

    package study5ran2yl.study; import java.util.Scanner; public class demo11 { public static void main( ...

  7. 001 Redis 配置

    Redis缓存 1.配置Redis //Redis 配置文件 @Configuration public class RedisConfiguration { @Bean public RedisTe ...

  8. 5-7 分页查询PageHelper

    1. PageHelper实现分页查询 Day08 1.1 PH作用: PageHelper框架可以实现我们提供页码和每页条数, 自动实现分页效果,收集分页信息 1.2 PH原理: PageHelpe ...

  9. Solution -「校内题」矩阵求和

    Description 共 \(T\) 组数据.对于每组数据,给定 \(a, b, n\),求 \(\sum_{i = 1}^{n} \sum_{j = 1}^{n} \gcd(a^i - b^i, ...

  10. Unity3D学习笔记9——加载纹理

    目录 1. 概述 2. 详论 2.1. Resources方式 2.2. API方式 2.3. Web方式 1. 概述 理论上,Unity中加载纹理并没有什么难度,只需要将图片放置在Assets文件夹 ...