vue3.0搭配.net core实现文件上传组件


Posted in Javascript onOctober 29, 2020

在开发Web应用程序中,文件上传是经常用到的一个功能。
在Jquery时代,做上传功能,一般找jQuery插件就够了,很少有人去探究上传文件插件到底是怎么做的。
简单列一下我们要做的技术点和功能点

使用技术

客户端使用vue.js 3.0,并使用vue3新增的功能:Composition API ,服务器使用asp.net core

功能点

  1. 标签美化
  2. 文件预览
  3. 文件上传
  4. 服务器接收文件

文件选择美化

在标准的html文件选择标签,是十分不美观的。大概就是下图的样子

vue3.0搭配.net core实现文件上传组件

但是我们的设计师的设计图可不是这样的啊,所以第一步是选择美化一下样式。

标签美化

找遍整个搜索引擎,美化文件选择标签只有两种方法

  1. 设置input标签透明度为0,然后定位一个其他的容易修改样式的标签到透明度度为0的input标签上。
  2. 设置input标签的display为none,然后使用JavaScript来触发当前input的点击事件。

因为笔者最近在做基于vue.js 3.0的项目,需要自己自定义很多UI组件,所以参考了layui element ,它们都是使用第二种方式来美化文件选择标签。

vue3.0搭配.net core实现文件上传组件

假设我们UI设计图是上图的样式,如果需要美化,只需要隐藏文件选择的Input标签。然后放置一个按钮,然后设置按钮的样式为设计图上的样式即可

<div class="uploader">
  <button>选择文件</button>
  <input type="file" placeholder="请选择文件" />
 </div>
.uploader {
 display: inline-block;
 button {
  background: #4e6ef2;
  color: aliceblue;
  padding: 5px;
  outline: none;
  border: none;
  &:hover {
   opacity: 0.8;
  }
  &:active {
   opacity: 1;
  }
 }
 input {
  display: none;
 }
}

美化完成组件后,我们需要用在button点击的时候,使用JavaScript去点击隐藏的input标签

<template>
 <div class="uploader">
  <button @click="btnClick">选择文件</button>
  <input type="file" placeholder="请选择文件" ref="fileSelector" />
 </div>
</template>
 
<script>
import { ref } from "vue";
export default {
 name: "uploader",
 setup() {
  const fileSelector = ref(null);
  const btnClick = () => {
   fileSelector.value.click();
  };
  return {
   fileSelector,
   btnClick,
  };
 },
};
</script>

在Composition api中要获取到标签的ref,不能使用this.$refs来获取。当然,你如果喜欢使用vue2的options api。那依然可以使用this.$refs来获取标签的el
只需要简单的触发input的click事件,就可以使浏览器弹出文件选择框了。

文件预览

基本上所有的文件上传组件,都有预览上传图片的功能。本文所写的上传组件当然也不例外。
监听input标签的change事件,获取到files对象。然后使用FileReader读取文件信息。

const fileChange = (e) => {
   let files = e.target.files;
   console.log(files);
   for (let i = 0; i < files.length; i++) {
    let file = files[i];
    var fileReader = new FileReader();
    fileReader.addEventListener(
     "load",
     (event) => {
      console.log(event);
      data.imgList.push({
       base64: event.target.result,
      });
     },
     false
    );
    fileReader.readAsDataURL(file);
   }
  };

vue3.0搭配.net core实现文件上传组件

在Chromium内核等高版本浏览器中,无法像低版本浏览器一样,能获得文件的具体磁盘路径。如果像以前用文件路径去获取文件。只能获得一个 C:\fakepath"+文件名的路径。无法获取到真实文件路径。据说可以通过某些方法获取真实路径。我试过,没成功。有兴趣的朋友可以试试。

文件上传

选择文件后,我们需要把文件保存到到服务器。在传统的多页面web程序中,只需要设置按钮的type为submit,然后使用form表单直接提交文件和表单信息到服务器去。
但是我们做单页面程序,一般来说是通过JavaScript的ajax去上传文件。

const uploadServer = (file) => {
   var form = new FormData();
   form.append("file", file);
   var xhr = new XMLHttpRequest();
   xhr.open("post", props.server);
   xhr.onreadystatechange = () => {
    if (xhr.readyState == 4 && xhr.status == 200) {
     var res = JSON.parse(xhr.responseText);
     console.log("上传成功");
     data.logs.push({
      log: res,
     });
    }
   };
   xhr.upload.onprogress = (event) => {
    if (event.lengthComputable) {
     var percent = (event.loaded / event.total) * 100;
     console.log("上传进度:" + percent);
    }
   };
   xhr.onerror = () => {
    console.log("上传文件错误");
   };
   xhr.ontimeout = () => {
    console.log("上传超时");
   };
   xhr.send(form);
  };

在页面上新增一个按钮,用来手动触发上传

<div class="uploader">
  <button @click="btnClick">选择文件</button>
  <button @click="uploadClick">立即上传</button>
  <input
   type="file"
   placeholder="请选择文件"
   ref="fileSelector"
   @change="fileChange"
   multiple
  />
  <div class="image-list">
   <img v-for="(item, i) in data.imgList" :key="i" :src="item.base64" />
  </div>
  <div class="log">
   <p v-for="(item, i) in data.logs" :key="i">{{ item.log }}</p>
  </div>
 </div>

点击 立即上传 按钮,触发上传

const uploadClick = () => {
   data.files.forEach((file) => {
    uploadServer(file);
   });
  };

vue3.0搭配.net core实现文件上传组件

服务器接收

在服务器编程中,我们使用C#来接收上传的文件。

/// <summary>
    /// 上传
    /// </summary>
    /// <param name="files"></param>
    /// <returns></returns>
    [HttpPost("/upload")]
    public async Task<IActionResult> Upload([FromServices] IWebHostEnvironment host)
    {
      var files = Request.Form.Files;
      long size = files.Sum(f => f.Length);
      List<string> list = new List<string>();
      foreach (var formFile in files)
      {
        if (formFile.Length > 0)
        {
          var path = Path.Combine(host.WebRootPath, "files");
          
          if (!Directory.Exists(path))
          {
            Directory.CreateDirectory(path);
          }
          string fileName = $"{Guid.NewGuid():N}{Path.GetExtension(formFile.FileName)}";
          path = Path.Combine(path, fileName);
          var filePath = path;
 
          using var stream = System.IO.File.Create(filePath);
          await formFile.CopyToAsync(stream);
          var c = Path.VolumeSeparatorChar;
          list.Add($"{Request.Scheme}://{Request.Host.Value}/{Path.Combine("files", fileName).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)}");
        }
      }
 
      return Ok(new { list = list, size });
    }

使用dotnet run运行asp.net core服务端。然后点击上传,你以为就上传成功了吗?
不!没那么简单。如果如果vue程序和asp.net core程序,不在同一个域名下,你还得处理上传跨域问题。当然这个问题在asp.net core中是非常简单的。只需要简单配置一下即可

如果在IIS或者Nginx下,就需要修改对应站点的配置文件了。当然具体服务器软件的配置不在本篇文章的讨论之下。有需要的同学可以私下交流
asp.net core跨域处理

app.UseCors(options =>
      {
        options.WithOrigins("http://localhost:3000", "http://127.0.0.1", "http://localhost:8080"); // 允许特定ip跨域
        options.AllowAnyHeader();
        options.AllowAnyMethod();
        options.AllowCredentials();
      });

以上配置必须要放在app.UseStaticFiles();之前才会生效。

上传成功后,你就会在服务器的wwwroot的files文件夹中看到上传的图片文件了。

vue3.0搭配.net core实现文件上传组件

本文完成了基本的功能,起一个抛砖引玉的作用。更多功能,如:文件类型限制,文件大小限制等,可以根据使用场景自定义扩展

本篇vue 3.0文件上传组件开发到这里就结束了。

以上就是vue3.0搭配.net core实现文件上传组件的详细内容,更多关于vue3.0 文件上传的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
DOM 脚本编程中的兄弟节点
Oct 31 Javascript
jQuery Ajax请求状态管理器打包
May 03 Javascript
将json对象转换为字符串的方法
Feb 20 Javascript
JSON+HTML实现国家省市联动选择效果
May 18 Javascript
javascript判断是手机还是电脑访问网页的简单实例分享
Jun 03 Javascript
微信分享的标题、缩略图、连接及描述设置方法
Oct 14 Javascript
使用jQuery管理选择结果
Jan 20 Javascript
Jquery1.9.1源码分析系列(十五)动画处理之外篇
Dec 04 Javascript
javascript基础练习之翻转字符串与回文
Feb 20 Javascript
详解Vue CLI3配置之filenameHashing使用和源码设计使用和源码设计
Aug 31 Javascript
JavaScript中引用vs复制示例详析
Dec 06 Javascript
vue2路由方式--嵌套路由实现方法分析
Mar 06 Javascript
使用jQuery实现购物车
Oct 29 #jQuery
ant design中upload组件上传大文件,显示进度条进度的实例
Oct 29 #Javascript
react使用antd表单赋值,用于修改弹框的操作
Oct 29 #Javascript
node.js爬虫框架node-crawler初体验
Oct 29 #Javascript
JavaScript实现网页计算器功能
Oct 29 #Javascript
Javascript数组及类数组相关原理详解
Oct 29 #Javascript
antd Form组件方法getFieldsValue获取自定义组件的值操作
Oct 29 #Javascript
You might like
PHP初学者常见问题集合 修正版(21问答)
2010/03/23 PHP
PHP实现WebService的简单示例和实现步骤
2015/03/27 PHP
php图像处理函数imagecopyresampled用法详解
2016/12/02 PHP
Yii 2.0实现联表查询加搜索分页的方法示例
2017/08/02 PHP
自己整理的一个javascript日期处理函数
2010/10/16 Javascript
JavaScript内核之基本概念
2011/10/21 Javascript
再探JavaScript作用域
2014/09/24 Javascript
JavaScript中字符串(string)转json的2种方法
2015/06/25 Javascript
BootstrapTable与KnockoutJS相结合实现增删改查功能【二】
2016/05/10 Javascript
vue之数据交互实例代码
2017/06/20 Javascript
解决AjaxFileupload 上传时会出现连接重置的问题
2017/07/07 Javascript
浅析JS中常用类型转换及运算符表达式
2017/07/23 Javascript
浅析从vue源码看观察者模式
2018/01/29 Javascript
Vue.js的动态组件模板的实现
2018/11/26 Javascript
详解利用nodejs对本地json文件进行增删改查
2019/09/20 NodeJs
JavaScript对象原型链原理解析
2020/01/22 Javascript
node.js实现http服务器与浏览器之间的内容缓存操作示例
2020/02/11 Javascript
[02:49]2014DOTA2电竞也是体育项目! 势要把荣誉带回中国!
2014/07/20 DOTA
[03:24]CDEC.Y赛前采访 努力备战2016国际邀请赛中国区预选赛
2016/06/25 DOTA
[01:10:27]DOTA2-DPC中国联赛正赛 SAG vs XG BO3 第二场 3月5日
2021/03/11 DOTA
python实现将汉字转换成汉语拼音的库
2015/05/05 Python
Python时间获取及转换知识汇总
2017/01/11 Python
Python字典操作详细介绍及字典内建方法分享
2018/01/04 Python
python实现年会抽奖程序
2019/01/22 Python
基于PyQt4和PySide实现输入对话框效果
2019/02/27 Python
python栈的基本定义与使用方法示例【初始化、赋值、入栈、出栈等】
2019/10/24 Python
详解Python 实现 ZeroMQ 的三种基本工作模式
2020/03/24 Python
python小白切忌乱用表达式
2020/05/29 Python
解决pip install psycopg2出错问题
2020/07/09 Python
Boston Proper官网:美国女装品牌
2017/10/30 全球购物
Bose法国官网:购买耳机、扬声器、家庭影院、专业音响
2017/12/21 全球购物
迪卡侬波兰体育用品商店:Decathlon波兰
2020/03/31 全球购物
linux面试题参考答案(7)
2012/10/29 面试题
疾病防治方案
2014/05/31 职场文书
安全保证书格式
2015/02/28 职场文书
电子表的操作介绍说明书
2019/10/28 职场文书