学习ASP.NET Core Blazor编程系列十七——文件上传(上)

 从本篇文章开始我们来讲在图书租赁系统中如何使用内置的文件上传组件进行文件上传功能的开发。本文的示例适合上传小型文件。本篇文章演示如何通过Blazor的内置组件InputFile将文件上传至服务器。

     安全注意事项

  在向用户提供向上传文件的功能时,必须格外注意安全性。攻击者可能对系统执行拒绝服务和其他攻击。所以在提供上传功能时需要注意以下安全措施:

    1. 将文件上传到系统上的专用文件上传目录,这样可以更轻松地对上传内容实施安全措施。如果允许文件上传,请确保在上传目录禁用执行权限。

    2. 上传文件的文件名在服务器端保存时要由应用程序自动重新命名文件名称,而不是采用用户输入或已上传文件的文件名。

    3.请不要将上传的文件保存在与应用程序相同的目录下。

    4. 仅允许使用一组特定的文件扩展名。

    5. 在服务端重新执行客户端检查。 不要相信客户端检查,因为客户端检查很容易规避。

    6. 检查上传文件大小,防止上传文件的大小比预期的文件大小大。

    7. 对上传文件的内容进行病毒/恶意软件扫描程序。

    8.应用程序中的文件不能被具有相同名称的上传文件覆盖。

警告

   将恶意代码上传到系统通常是执行代码的第一步,这些代码可以实现以下功能:

   1. 完全接管系统。

   2. 重载系统,导致系统完全崩溃。

   3. 泄露用户或系统数据。

一、添加一个用于上传文件的文件辅助类FileHelpers

为避免处理上传文件文件时出现重复代码,我们首先创建一个静态类用于处理上传功能。

   1.在Visual Studio 2022 的解决方案资源管理器中创建一个“Utils”文件夹。

   2.在Visual Studio 2022的解决方案资源管理器中,鼠标左键选中“Utils”文件夹,右键单击,在弹出菜单中选择“添加—>类”(如下图)。 将类命名为“FileHelpers”。

 

   3.在Visual Studio 2022的文本编辑器中打开我们刚才创建的“FileHelpers.cs”类文件,并添加以下内容。其中方法 ProcessFormFile 接受 IBrowserFile 和 ModelStateDictionary等参数,保存成功则空字符串,否则返回错误信息。 检查内容类型和长度。 如果上传文件未通过校验,将向 ModelState 添加一个错误。

using BlazorAppDemo.Models;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Reflection;
using System.Text;
 
namespace BlazorAppDemo.Utils
{

    public class FileHelpers
    {

        public static async Task<string> ProcessFormFile(IBrowserFile formFile, ModelStateDictionary modelState,IWebHostEnvironment envir,int maxFileSize)
        {
            var fieldDisplayName = string.Empty;        
 
            if (!string.IsNullOrEmpty(formFile.Name))
            {
                // 如果名称没有找到,将会有一个简单的错误消息,但不会显示文件名称
                string displayFileName = formFile.Name.Substring(formFile.Name.IndexOf(".") + 1);

                fieldDisplayName = $"{displayFileName} ";
               
            }
 
            //使用path.GetFileName获取一个带路径的全文件名。
            //通过HtmlEncode进行编码的结果必须在错误消息中返回。
            var fileName = WebUtility.HtmlEncode(Path.GetFileName(formFile.Name));
 
            if (formFile.ContentType.ToLower() != "text/plain")
            {
                modelState.AddModelError(formFile.Name,
                                         $"The {fieldDisplayName}file ({fileName}) must be a text file.");
            }
 
 
            //校验文件长度,如果文件不包含内容,则不必读取文件长度。
            //此校验不会检查仅具有BOM(字节顺序标记)作为内容的文件,
            //因此在读取文件内容后再次检验文件内容长度,以校验仅包含BOM的文件。
            if (formFile.Size == 0)
            {
                modelState.AddModelError(formFile.Name, $"The {fieldDisplayName}file ({fileName}) is empty.");

            }
            else if (formFile.Size > maxFileSize)
            {

                modelState.AddModelError(formFile.Name, $"The {fieldDisplayName}file ({fileName}) exceeds 1 MB.");
            }
            else
            {
                try
                {
                  

                    //获取一个随机文件名
                    var trustedFileNameForFileStorage=Path.GetRandomFileName();
                    var path = Path.Combine(envir.ContentRootPath, envir.EnvironmentName, "unsafeUploads", trustedFileNameForFileStorage);
 
                    using (
                        var reader =
                            new FileStream(
                                path,
                                FileMode.Create))
                    {
                        await formFile.OpenReadStream(maxFileSize).CopyToAsync(reader);
                    }

                }
                catch (Exception ex)
                {
                    modelState.AddModelError(formFile.Name,

                                             $"The {fieldDisplayName}file ({fileName}) upload failed. " +

                                             $"Please contact the Help Desk for support. Error: {ex.Message}");
             //return ex.Message;
               throw ex;
                }
            }
            return string.Empty;
        }

    }

}

 

二、添加前端代码

1.  在Visual Studio 2022的解决方案资源管理器中,鼠标右键单击“Pages”文件夹。在弹出菜单中选择,添加-->Razor组件。如下图。

 

2.在弹出对话框,名称中输入FileUpload1.razor。如下图。

3. 在Visual Studio 2022的解决方案资源管理器中,鼠标左键双击“Pages\FileUpload1.razor”文件,在文本编辑器中打开,在文件的顶部添加@page指令。并添加如下代码。

@page "/FileUpload1"
@using BlazorAppDemo.Utils
@using Microsoft.AspNetCore.Mvc.ModelBinding
@inject IWebHostEnvironment Environ
<h3>多文件上传示例</h3>
<p>
    <label>
        提示信息:@Message
 
    </label>
</p>
<p>
    <label>
        上传文件最大可以为:<input type="number" @bind="maxFileSize"/>字节
 
    </label>
</p>
<p>
    <label>
        一次可上传:<input type="number" @bind="maxAllowedFiles" />个文件
 
    </label>
</p>
<p>
    <label>
        选择上传文件:<InputFile OnChange="@LoadFiles" multiple />
 
    </label>
</p>
@if (isLoading)
{
    <p>文件上传中......</p>
}
else
{
    <ul>
        @foreach (var file in loadedFiles)
        {
            <li>
                <ul>
                    <li>文件名:@file.Name</li>
                    <li>最后修改时间:@file.LastModified.ToString()</li>
                    <li>文件大小(byte):@file.Size</li>
                    <li>文件类型:@file.ContentType</li>
                </ul>
            </li>
           
        }
 
    </ul>
}
 
@code {
    private List<IBrowserFile> loadedFiles = new();
    private long maxFileSize = 1024 * 18;
    private int maxAllowedFiles = 2;
    private bool isLoading;
    private string Message = string.Empty;
 
    private async Task LoadFiles(InputFileChangeEventArgs e)
    {
        isLoading = true;
        loadedFiles.Clear();
        foreach (var file in e.GetMultipleFiles(maxAllowedFiles))
        {
            try
            {
                ModelStateDictionary modelState = new ModelStateDictionary();
                loadedFiles.Add(file);
                string result=  await FileHelpers.ProcessFormFile(file, modelState, Environ, maxFileSize);

                if (string.IsNullOrEmpty(result))
                {
                    Message = "上传成功!";
                }else
                Message = "上传失败!";
            }
            catch (Exception ex)
            {
                Message = ex.Message;
               
            }
        }
        isLoading = false;
    }
}

 

4. 在Visual Studio 2022的解决方案资源管理器中,鼠标左键双击“Shared\NavMenu.razor”文件,在文本编辑器中打开,我们在此文中添加指向上传文件的菜单。具体代码如下:

<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="">BlazorAppDemo</a>

        <button title="Navigation menu" class="navbar-toggler" @οnclick="ToggleNavMenu">
            <span class="navbar-toggler-icon"></span>
        </button>
    </div>
</div>
 
<div class="@NavMenuCssClass" @οnclick="ToggleNavMenu">
    <nav class="flex-column">
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="BookIndex">
                <span class="oi oi-list-rich" aria-hidden="true"></span> 图书列表
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="AddBook">
                <span class="oi oi-list-rich" aria-hidden="true"></span> 添加图书
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="FileUpload1">
                <span class="oi oi-list-rich" aria-hidden="true"></span> 上传文件
            </NavLink>
        </div>
    </nav>
</div>

 
@code {
   private bool collapseNavMenu = true;

     private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {

        collapseNavMenu = !collapseNavMenu;

    }

} 

     5. 在Visual Studio 2022的菜单栏上,找到“调试à开始调试”或是按F5键,Visual Studio 2022会生成BlazorAppDemo应用程序,并在浏览器中打开Home页面,我们使用鼠标点击左边的菜单栏上的“上传文件”菜单项,页面会进入“FileUpload1”页面,我们会看到我们写的图书列表页面,如下图。

 

6. 我们在“多文件上传示例”中选择一个上传文件,然后应用程序会自动上传文件,但是却会提示错误,错误信息如下图中1处,指明“找不到路径的一部分”。我们打开资源管理器,在项目中找一下图中2处的目录,发现没有这样的目录结构。我们手动创建一下即可。 

7. 我们在“多文件上传示例”中选择一个上传文件,然后应用程序会自动上传文件,上传到到目录中却不是我们选择的文件名,是一个随机的文件名。如下图。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ASP.NET Core Razor编程中,列表模板页面是非常常见的。这些页面通常用于显示数据库或其他数据源中的一组记录。 在本文中,我将向您展示如何使用ASP.NET Core Razor列表模板页面。 首先,我们需要创建一个模型类来代表我们的数据。例如,假设我们正在构建一个博客应用程序,我们需要一个名为“Post”的模型类来表示博客文章。以下是一个示例模型类: ```csharp public class Post { public int Id { get; set; } public string Title { get; set; } public string Content { get; set; } public DateTime CreatedDate { get; set; } } ``` 接下来,我们需要创建一个控制器类来处理与“Post”模型类相关的操作。以下是一个示例控制器类: ```csharp public class PostController : Controller { private readonly ApplicationDbContext _context; public PostController(ApplicationDbContext context) { _context = context; } public IActionResult Index() { var posts = _context.Posts.ToList(); return View(posts); } } ``` 在此示例控制器中,我们从数据库中检索所有博客文章,并将它们递给视图。 现在,我们需要创建一个视图来显示我们的博客文章列表。我们可以使用ASP.NET Core Razor模板引擎来创建一个动态模板,该模板可以将我们的博客文章显示为HTML表格。以下是一个示例视图: ```html @model IEnumerable<Post> <table> <thead> <tr> <th>Title</th> <th>Content</th> <th>Created Date</th> </tr> </thead> <tbody> @foreach (var post in Model) { <tr> <td>@post.Title</td> <td>@post.Content</td> <td>@post.CreatedDate.ToShortDateString()</td> </tr> } </tbody> </table> ``` 在此示例视图中,我们使用了一个foreach循环遍历我们的博客文章,并将它们显示为HTML表格行。 最后,我们需要在控制器的Index方法中返回视图。在我们的示例控制器中,我们已经递了一个包含所有博客文章的IEnumerable<Post>对象。我们可以将此对象递给视图,如下所示: ```csharp public IActionResult Index() { var posts = _context.Posts.ToList(); return View(posts); } ``` 现在,当我们访问PostController的Index操作时,我们将看到一个包含所有博客文章的HTML表格。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野生的狒狒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值