65.9K
CodeProject 正在变化。 阅读更多。
Home

在 ASP.NET Core 3.1 MVC 中集成 Vue.js V4 和使用 Dropzone 进行文件上传

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (10投票s)

2020年2月15日

CPOL

10分钟阅读

viewsIcon

32347

downloadIcon

725

在 ASP.NET Core 3.1 MVC 中配置 Vue.js v4。介绍 Node.js、NPM、WebPack 和 DropZone。使用 NPM 和 WebPack 的任务运行器进行编译和打包。

引言

我们习惯于通过浏览器将文件从用户计算机/系统传输到网站上的不同服务器。这个过程称为文件上传。我们知道在单页应用程序(Single-Page-Application)中,整个页面在初始请求期间加载到浏览器中,之后,它可以更新已更改的特定部分/页面。这样我们就不需要为每次更新重新加载整个页面。无论如何,为了完成文件上传,我们可以将其分为两个部分。文件上传的前端/UI 部分将使用 Vue.js 处理,逻辑文件保存部分/后端将使用 ASP.NET Core 3.1 MVC 处理。单个文件将使用 IFormFile 缓冲在内存中,文件内容将以流的形式访问。

涵盖主题

  1. Node.js 和 NPM 的介绍与安装
  2. Vue.js V4 的介绍与安装
  3. 用于 .NET Core 3.1 的 VS 2019 的介绍与安装
  4. NPM 和 WebPack 任务运行器的介绍与运行说明
  5. 将 Vue.js 与 ASP.NET Core 3.1 MVC 集成/配置
  6. 使用 Vue.js 和 ASP.NET Core MVC 配置/设置 DropZone

必备组件

  • 用于 .NET Core 3.1 的 Visual Studio 2019
  • 安装 Node.js、NPM 和 Vue.js
  • WebPack 任务运行器以可视化方式编译 JS 文件
  • NPM 任务运行器以可视化方式安装/更新包

你不喜欢学习但喜欢学东西吗?好的!这里有一些问题给你!

  • 为什么选择 Vue.js? - 你可以选择 JS 框架吗(例如 Angular/React/Vue.js 等)?如果可以,那么哪个对你来说是好的,为什么?或者你没有选择权,你的团队已经为你选择了 JS 框架(例如 Vue.js)?如果是这样,那么他们为什么选择它,因为有替代品?
  • 为什么选择 NPM? - 你可以选择 Bower、Yarn 或 NPM,那么为什么选择 NPM?
  • 为什么选择 WebPack? - 你可以选择 Grunt、Gulp 或 WebPack,那么为什么选择 WebPack?

Node.js 介绍

  • Node.js 是开源命令行工具。它使用 Google V8 JavaScript 引擎执行代码。
  • Node.js/NPM 的安装 - 要下载 Node.js,请单击链接(https://node.org.cn/en/download/
  • 为什么需要 Node.js/NPM - 简而言之,你可能需要在应用程序中安装第三方包。NPM 是命令行实用程序,可帮助你安装所需的包。但没有 Node.js,你无法安装 NPM。系统会要求你在安装 Node.js 时安装 NPM。因此,安装 Node.js 以运行 NPM。

你是否已安装 Node.js/NPM?

打开命令行,键入:node -v 并按 Enter。如果获得版本号,则表示你的机器上已经安装了它。

  • 要检查 npm 版本,请使用以下命令:npm -v
  • 要升级 npm 版本,请使用以下命令:npm i -g npm

Node/NPM 版本相关常见错误

假设你的系统中有旧版本,并且已升级到最新版本。现在,如果在使用以下命令:npm -v 检查版本时遇到任何错误(例如,“TypeError: log.gauge.isEnabled”),那么这是 npm 包依赖问题。从以下路径删除所有目录/文件,然后重新安装/修复 Node.js

  • C:\Users\[User-Name]\AppData\Roaming\npm-cache
  • C:\Users\[User-Name]\AppData\Roaming\npm

Vue.js 介绍

Vue.js 是一个用于单页应用程序(SPA)开发的 JavaScript 框架。它类似于 Angular、React.js 或 Knockout,并避免页面重新加载。它们各自有不同的侧重点,你需要根据自己的情况决定哪个适合你。如果你需要进行动态 DOM 操作,那么 React.js 很好。如果你需要数据驱动的 CRUD 操作,那么 Angular 很好。Vue.Js 的位置介于这些情况之间;但它仍然喜欢处理动态 DOM 操作。但是,这是我的个人看法!

Vue.js V4 的安装

使用以下命令全局安装新版本:npm install -g @vue/cli
为什么需要卸载以前版本的 vue-cli? - 如果你已全局安装 vue-cli 包(版本:1.0/2.0)并想使用新的 v4,那么你必须卸载以前的版本。新版本 v4 已从 vue-cli 更改为 @vue/cli。

  • 要检查版本,请使用以下命令:vue --version
  • 要使用 NPM 全局卸载它,请使用命令:npm uninstall vue-cli -g
  • 要使用 NPM 全局安装它,请使用命令:npm install -g @vue/cli

.NET Core 介绍

我不需要介绍 .NET Framework。但是,如果你打算在 Windows、Mac 和/或 Linux 等多个平台上运行应用程序,那么 .NET Core 是完美的,因为它专注于微服务。另一个考虑因素是,如果你需要 Docker 容器,那么你知道容器比虚拟机 (VM) 更轻量。

Visual Studio 2019 的安装

WebPack/NPM 任务运行器资源管理器介绍

Web-pack 任务运行器资源管理器用于编译和捆绑 JS 文件;而 NPM 任务运行器资源管理器用于安装/更新依赖包。

适用于 VS 2019 的 NPM/WebPack 任务运行器的下载和运行说明

为什么需要 NPM 任务运行器?

当你希望在应用程序中手动安装/更新第三方包时,这是必需的。“package.json”文件用于保存包列表并与 Node.js 和 NPM 一起工作。在此文件中,你可以添加依赖项,其中包名称和版本如下所示:
devDependencies”: {“PackageName”: “VersionNumber”}

Web-Pack 如何工作

让我们看看以下情况

  • 最终用户:Eva,我喜欢你的 T 恤。你从哪里买的?我想买一件。
  • Eva.js:John 送我的。
  • 最终用户:好的,和 John 谈谈,问他从哪里买的。
  • Eva.js:嘿 John,去年圣诞节,你送我的 T 恤是从哪里买的?
  • John.js:我从印度的 ABC 商店买的。

因此,最终用户发送了一个或多个 Http 请求以获得预期结果。这意味着,存在一个依赖图,其中 Eva.js 调用 John.js。现在,如果你想将这两个 JS 文件合并到一个捆绑包中,那么单个 http 请求即可找到该文件。因此,你需要 Web-Pack 来创建这些捆绑包。你可以使用 Web-Pack 连接、缩小和/或丑化你的 JS 文件。(连接是将所有文件附加到一个大文件中;缩小是删除不必要的空白和字符而不改变功能;丑化是将代码转换为难以理解的格式。)

为什么需要 Web-Pack 任务运行器?

简而言之,考虑到上述情况,我们可以说你需要 Web-Pack 任务运行器来编译和捆绑 JS 文件。

webpack.config.js”文件拉取所有配置,它有一个入口点来引入所有 JS 文件配置,其中捆绑器开始,然后它使用输出获取路径和文件名配置以生成捆绑包。

module.exports = { 
entry: { app: './wwwroot/js/app.js' }, 
output: { 
publicPath: "/dest/js/", 
path: path.join(__dirname, '/wwwroot/dest/js/'), 
filename: '[name].bundle.js'
 }
} 

将 Vue.JS 与 ASP.NET Core MVC Web 应用程序集成

项目创建

假设你可以创建一个新项目“ASP.NET Core Web Application>Web Application (Model-View-Controller)”。现在,如果你不想使用默认的 jQuery 库,那么你可以从“wwwroot>lib”中删除文件和文件夹。但是,这是可选的。

模板设计

你可以根据自己的要求修改默认的 site.css 和 site.js 文件。

在项目的 App.js 文件中添加 Bootstrap

在“wwwroot/css”目录中,我添加了用于 CSS 的 app.css 文件,并在“wwwroot/js”目录中,我添加了 app.js 文件,并注册了“Bootstrap”插件以使用材料图标,最终结果如下:

import $ from 'jquery';
//// Import the Bootstrap Material Design Theme
import 'bootstrap-material-design/dist/css/bootstrap-material-design.min.css';
import 'bootstrap-material-design/dist/js/bootstrap-material-design.min.js';
import 'material-design-colors/dist/material-design.min.css';

//// Import the App Styles
import '../css/app.css';

//// Initialize the Material Design elements when the page loads
$(document).ready(function () {
    $('body').bootstrapMaterialDesign
    $('[data-toggle="popover"]').popover

注意:我添加此文件仅作为示例。在此项目中,我避免了设计/材料图标,而专注于配置。

将 NPM 包添加到 package.json 中

你可能需要 Vue、babel、WebPack、bootstrap 等包。Babel 是一个 JavaScript 转译器,它编译和转换旧的 ES5 JavaScript 以使其与浏览器兼容。所有包都保存在“package.json”文件中。现在你可以使用 Package-Manager-Console 或 Task Runner Explorer 安装/更新这些包。例如,我添加了一些包,最终结果如下:

{
  "name": "HR.App.Web",
  "version": "1.1.1",
  "private": true,
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-preset-env": "^1.7.0",
    "babel-preset-es2017": "^6.24.1",
    "bootstrap": "^4.1.3",
    "bootstrap-material-design": "^4.1.1",
    "css-loader": "^1.0.0",
    "fuse.js": "^3.2.1",
    "jquery": "^3.3.1",
    "material-design-colors": "^1.0.2",
    "style-loader": "^0.19.0",
    "uglifyjs-webpack-plugin": "^1.3.0",
    "url-loader": "^0.6.2",
    "vue": "^2.6.10",
    "vue-loader": "^15.4.2",
    "vue-template-compiler": "^2.5.17",
    "webpack": "^4.20.2",
    "webpack-cli": "^3.1.1",
    "webpack-dev-server": "^3.1.9"
  },
  "dependencies": {}
}

如果你想使用 NPM 任务运行器资源管理器从 package.json 文件安装/更新包,请确保你已安装 NPM 任务运行器资源管理器。如果你没有看到任务运行器资源管理器,请选择 Package.json 并单击鼠标右键。现在,从任务运行器资源管理器中,从 package.json 中选择安装并单击鼠标右键,如下图所示。结果,所有包都将被安装。

WebPack 配置和捆绑 JS 文件

当 Web-Pack 任务运行器找到 webpack.config.js 文件时,它会自动触发。该文件最终结果如下:

"use strict";
const { VueLoaderPlugin } = require('vue-loader');
const path = require('path');
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
    entry: {
        app: './wwwroot/js/app.js',
        home: './Views/Home/Index.cshtml.js',
        errorDetail: './Views/Home/ErrorDetail.cshtml.js'
           },
    plugins: [
        new webpack.ProvidePlugin({
            '$': 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            Popper: ['popper.js', 'default']
        }),
        new VueLoaderPlugin()
    ],

    optimization: {
        minimizer: [
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                uglifyOptions: {
                    compress: false,
                    ecma: 6,
                    mangle: true
                },
                sourceMap: true
            })
        ]
    },
    output: {
        publicPath: "/dest/js/",
        path: path.join(__dirname, '/wwwroot/dest/js/'),
        filename: '[name].bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /(node_modules)/,
                query: {
                    presets: ['es2017']
                }
            },
            {
                test: /\.css$/,
                loaders: ['style-loader', 'css-loader']
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 8192
                    }
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            }
        ]
    },
    resolve: {
        alias: {
            vue: 'vue/dist/vue.js'
        },
        extensions: ['.js', '.vue']
    }
};

我已经在上面解释过,我们需要“Entry”来配置带有路径的 js 文件源,以便以后获得捆绑包。

entry: { app: './wwwroot/js/app.js', home: './Views/Home/Index.cshtml.js'}

Output:这是已编译 JavaScript 文件的输出路径和捆绑包名称的配置。

output: { publicPath: "/dest/js/", path: path.join(__dirname, '/wwwroot/dest/js/'),
        filename: '[name].bundle.js'}

如果你想使用 web-pack Task Runner Explorer 编译和捆绑 JS 文件,请确保你已安装 Web-Pack Task Runner Explorer。如果你没有看到任务运行器资源管理器,请选择 webpack.config.js 并单击鼠标右键。现在,从任务运行器资源管理器中,选择 webpack.config.js 中的“运行”并单击鼠标右键,如下图所示。结果,所有 JS 文件都将构建到输出目录(wwwroot\dest\js)中。

为什么选择 Drop-Zone?

它可以轻松地将文件拖放到其中,并将文件上传到服务器;轻量级 JavaScript 库,使用它所需的代码量最少。

在 JS 和视图文件中添加 Drop-Zone 并进行配置

  • 要安装 dropzone 包,请将 dropzone 添加到 package.json 文件的 devDependencies 中。"devDependencies": {vue2-dropzone": "2.0.0" }
  • 如果你打开 webpack.config.js 文件,你会发现我已经将 JavaScript 源文件和路径添加到入口中。入口:{home: './Views/Home/Index.cshtml.js'}
  • 在此项目中,在 View>Home 目录中找到“Index.cshtml”视图页面和“Index.cshtml.js”文件。打开 Index.cshtml 并添加 dropzone 和 JavaScript 捆绑文件。添加它们后,结果如下:

在 dropzone 中

  1. url: 用于发送上传的文件,它需要控制器路径和操作方法(“/Home/SubmitFile”)。
  2. use-custom-dropzone-options:如果你想自定义选项,则为 true;(我在 Index.cshtml.js 文件中添加了“useUploadOptions”变量。)
  3. dropzone-options:你可以在此处自定义 maxfilesmaxFileSizeInMBacceptedFilesdictDefaultMessage。(在 Index.cshtml.js 中找到“uploadOptions”)
  4. v-on:vdropzone-success:此方法在成功上传文件后使用。
  5. v-on:vdropzone-error:如果上传失败,则使用此方法。
  • Index.cshtml.js 文件在 Index.cshtml 中使用,捆绑包名为 home.bundle.js,最终结果如下:
    import Vue from 'vue';
    import Dropzone from 'vue2-dropzone';
    
    document.addEventListener('DOMContentLoaded', function (event) {
        let view = new Vue({
            el: document.getElementById('view'),
            components: {
                "dropzone": Dropzone
            },
            data: {
                message: 'This is the index page',
                useUploadOptions: true,
                uploadOptions: {
                  acceptedFiles: '.png,.jpg,.pdf',
                  dictDefaultMessage: 'To upload the file click here. Or, drop a file here.',
                  maxFiles: 1,
                  maxFileSizeInMB: 20,
                  addRemoveLinks: true
                }
            },
            methods: {
                onUploaded: function (file, response) {
                    if (response.status === "OK" || response.status === "200") {
                        console.log('Successfully uploaded!');
                    }
                    else {
                        this.isVisible = false;
                        console.log(response.message);
                    }
                },
                onUploadError: function (file, message, xhr) {
                    console.log("Message ====> " + JSON.stringify(message));
                }
            }
        });
    });
  • 转到 home 控制器文件并添加以下代码:
    [HttpPost("/Home/SubmitFile")]
    public async Task<ActionResult> SubmitFile(IFormFile file)
    {
           try
           {
                 //// To do: Validation
                 //// To do: check file-content
                 string webRootPath = hostingEnvironment.WebRootPath;
                 string fileLandingPath = Path.Combine(webRootPath, folderName);
    
                 StreamReader stream = new StreamReader(file.OpenReadStream());
    
                 if (!Directory.Exists(fileLandingPath))
                 {
                        Directory.CreateDirectory(fileLandingPath);
                 }
    
                 string filePath = string.Format("{0}\\{1}{2}", fileLandingPath,
                        Path.GetFileNameWithoutExtension(file.FileName), 
                        Path.GetExtension(file.FileName));
    
                 using (var fileStream = new FileStream(filePath, FileMode.Create))
                 {
                        await file.CopyToAsync(fileStream);
                 }
    
                 var jsonResult = Json(new { status = "OK" });
                 return jsonResult;
           }
           catch (Exception ex)
           {
                 return Json(new { status = "Error", message = ex.Message });
           }
    }
  • 现在选择 Web-pack 任务运行器来编译和捆绑 js 文件。选择“运行”并单击鼠标右键,然后你会找到“运行”和“绑定”选项。单击“运行”。等待几秒钟,你将在“wwwroot\dest\js”目录中获得结果。

  • 现在准备运行应用程序,运行后,你将找到以下上传控件:

注意:在本文中,我主要关注配置和设置。因此,我没有关注包的最新版本。你应该使用最新版本的包。

历史

  • 2020年2月15日:初始版本
© . All rights reserved.