ASP.NET Core 6 MVC 文件上传

概述

        应用程序中的文件上传是一项功能,用户可以使用该功能将用户本地系统或网络上的文件上传到 Web 应用程序。Web 应用程序将处理该文件,然后根据需要对文件进行一些验证,最后根据要求将该文件存储在系统中配置的用于保存文件的存储中,即本地存储、共享远程存储或数据库等。

        文件上传是一项重要功能,可用于上传用户的个人资料图片、客户 KYC 详细信息(如照片)、签名和其他支持文件。文件上传还可用于上传数据,用户可以使用 CSV 或XML文件格式一起提交记录列表,而不是一次提交一条记录。

        在本文中,我们将主要关注如何在 ASP.NET Core MVC 中实现文件上传。 IFormFile 接口是 Microsoft.AspNetCore.Http 命名空间的一部分,可用于在 ASP.NET Core 中上传一个或多个文件。 ASP.NET Core 支持使用缓冲模型绑定上传较小文件的文件,并使用无缓冲流上传较大文件的文件。

文件上传方法

        在 ASP.NET Core 中有两种方法可以执行文件上传。

        源码下载:https://download.csdn.net/download/hefeng_aspnet/90294631 

缓冲

        在此方法中,IFormFile(文件的 C# 表示)用于在 Web 服务器上传输、处理和保存文件。整个文件被读入 IFormFile 对象,因此服务器上的磁盘和内存要求将取决于并发文件上传的数量和大小。

        如果上传的任何单个文件大于 64KB,则该文件将从内存移动到磁盘上的临时文件。如果应用程序或 Web 服务器资源因文件过大和并发文件上传过多而耗尽,则应考虑在这种情况下使用流式传输方法。

流媒体

        在这种方法中,文件以多部分请求的形式上传,并由应用程序直接处理或保存。与缓冲方法相比,上传文件流式方法消耗的内存或磁盘空间更少。在 Web 服务器上上传较大文件时,流式传输应该是首选方法。

在ASP.NET Core中实现文件上传

        为了开发演示应用程序,我们将使用带有 .NET 6.0 SDK 的 Visual Studio Community 2022 版本 17.2.1。

总体方法

为了演示如何在 ASP.NET Core 中执行文件上传,我们将采用以下方法:

        1、我们将首先创建一个 ASP.NET Core MVC 类型的应用程序并将其命名为 ProCodeGuide.Samples.FileUpload。

        2、我们将实现两种类型的文件上传,即针对小文件的缓冲模型绑定和针对大文件的流式上传。

        3、我们将添加具有所需 ViewModel 的所需控制器,将文件作为输入并将其保存到本地文件夹。

        4、我们将添加视图,用户可以使用该视图从本地文件系统中选择文件进行上传,并将文件提交给控制器操作方法。

        5、最后,我们将运行应用程序并测试 ASP.NET Core 中的文件上传功能。

创建 ASP.NET Core 项目进行演示

根据下面的屏幕截图创建一个 ASP.NET Core MVC 类型的新项目,项目名称为 ProCodeGuide.Samples.FileUpload

        我们将使用该项目来演示在 ASP.NET Core 中执行文件上传的两种类型,即缓冲和流式上传。

使用缓冲模型绑定上传小文件

        在这里,我们将看到如何使用缓冲模型绑定上传小文件。为了在 ASP.NET Core 中执行文件上传,我们将使用缓冲模型绑定方法,该方法易于实现,可用于上传小文件。

添加服务

        我们将添加一个服务,该服务将以 IFormFile 作为输入,并将提交的文件保存到路径环境当前目录下名为 UploadedFile 的文件夹中。此服务将在控制器中用于保存作为缓冲模型绑定发布的文件。

        我们将在 Interfaces/IBufferedFileUploadService.cs 下为接口添加以下代码

public interface IBufferedFileUploadService
{
    Task<bool> UploadFile(IFormFile file);
}

        我们将在 Services/BufferedFileUploadLocalService.cs 下为服务添加以下代码 

public class BufferedFileUploadLocalService : IBufferedFileUploadService
{
    public async Task<bool> UploadFile(IFormFile file)
    {
        string path = "";
        try
        {
            if (file.Length > 0)
            {
                path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "UploadedFiles"));
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                using (var fileStream = new FileStream(Path.Combine(path, file.FileName), FileMode.Create))
                {
                    await file.CopyToAsync(fileStream);
                }
                return true;
            }
            else
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            throw new Exception("File Copy Failed", ex);
        }
    }

在上述服务中的代码:

    1、使用 IFormFile 通过模型绑定来访问上传的文件。
    2、Path.GetFullPath 用于获取保存上传文件的完整限定路径。
    3、如果不存在,则使用 Directory.CreateDirectory 来创建完整限定路径。
    4、使用 Stream 访问 IFormFile 中文件的内容。
    5、路径和文件名一起传递给文件流。如果没有指定文件名,则会抛出异常。
    6、使用 IFormFile 提供的文件名将文件保存到指定路径上的文件系统。(这样做是为了保持代码简单,否则您应该生成一个新文件名,而不是使用用户指定的文件名)。

现在我们已经添加了服务,我们将在依赖项容器中注册该服务,以便可以使用构造函数将其注入到控制器中。要在依赖项容器中注册服务,我们将在 Program.cs 文件中添加以下代码行。

builder.Services.AddTransient<IBufferedFileUploadService, BufferedFileUploadLocalService>(); 

添加控制器

        现在让我们添加用于缓冲文件上传的 MVC 控制器,它将实现获取操作来显示视图和后期操作来处理 ASP.NET Core 中的文件上传。

我们将在 Controllers\BufferedFileUploadController.cs 下添加一个控制器,代码如下:

public class BufferedFileUploadController : Controller
{
    readonly IBufferedFileUploadService _bufferedFileUploadService;

    public BufferedFileUploadController(IBufferedFileUploadService bufferedFileUploadService)
    {
        _bufferedFileUploadService = bufferedFileUploadService;
    }

    public IActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public async Task<ActionResult> Index(IFormFile file)
    {
        try
        {
            if (await _bufferedFileUploadService.UploadFile(file))
            {
                ViewBag.Message = "File Upload Successful";
            }
            else
            {
                ViewBag.Message = "File Upload Failed";
            }
        }
        catch (Exception ex)
        {
            // Log ex
            ViewBag.Message = "File Upload Failed";
        }
        return View();
    }
}

        在上面的控制器中,我们通过依赖注入的构造函数注入了 BufferedFileUploadService。

        上述后期操作将文件输入作为 IFormFile,并且使用 IFormFile 上传的文件在控制器或服务中处理文件之前缓冲在服务器的内存或磁盘中。

添加视图

        我们将添加视图以允许用户选择要上传的文件并将其提交到服务器。我们将根据以下代码在 Views\BufferedFileUpload\Index.cshtml 下添加一个视图:

<h1>Buffered File Upload</h1>
<hr />
<form method="post" enctype="multipart/form-data">
    <input type="file" name="file" /> 
    <button type="submit">Upload File</button>
</form>
 
@if (ViewBag.Message != null)
{
    <div class="alert" style="margin-top: 20px">
        @ViewBag.Message
    </div>
}

        为了在 ASP.NET Core 中执行文件上传,HTML 表单必须指定编码类型 (enctype) 为 multipart/form-data。

        要使输入元素上传文件,您需要将输入类型指定为“文件”。

什么是 multipart/form-data?

        multipart/form-data 只是 post 方法的 content-type 标头之一。此内容类型主要用于将文件作为请求的一部分发送。使用此内容类型意味着每个值都作为数据块发送。

运行并测试代码

        最后,添加所有必需的代码后,编译并执行代码。执行后,导航到路径 /BufferedFileUpload/Index,它应该会显示如下所示的屏幕。

        在上面的屏幕上,您可以选择要上传的文件,然后单击“上传文件”按钮以在 ASP.NET Core 中执行文件上传。成功提交后,您应该能够在服务器上的 UploadedFiles 文件夹下看到该文件。

使用流式传输上传大文件

        在这里,我们将看到如何使用流式传输上传大文件。为了在 ASP.NET Core 中执行文件上传,我们将使用可用于上传较大文件的流式传输方法。

添加服务

        我们将添加一个服务,它将以流的形式读取文件输入,并将提交的文件保存到路径环境当前目录下名为 UploadedFile 的文件夹中。此服务将在控制器中用于将发布的文件保存为流。

        我们将在 Interfaces/IStreamFileUploadService.cs 下为接口添加以下代码

 public interface IStreamFileUploadService
{
    Task<bool> UploadFile(MultipartReader reader, MultipartSection section);
}

        我们将在 Services/StreamFileUploadLocalService.cs 下为服务添加以下代码 

public class StreamFileUploadLocalService : IStreamFileUploadService
{
    public async Task<bool> UploadFile(MultipartReader reader,MultipartSection? section)
    {
        while (section != null)
        {
            var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(
                section.ContentDisposition, out var contentDisposition
            );

            if (hasContentDispositionHeader)
            {
                if (contentDisposition.DispositionType.Equals("form-data") &&
                (!string.IsNullOrEmpty(contentDisposition.FileName.Value) ||
                !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value)))
                {
                    string filePath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "UploadedFiles"));
                    byte[] fileArray;
                    using (var memoryStream = new MemoryStream())
                    {
                        await section.Body.CopyToAsync(memoryStream);
                        fileArray = memoryStream.ToArray();
                    }
                    using (var fileStream = System.IO.File.Create(Path.Combine(filePath, contentDisposition.FileName.Value)))
                    {
                        await fileStream.WriteAsync(fileArray);
                    }
                }
            }
            section = await reader.ReadNextSectionAsync();
        }
        return true;
    }
}

        在此模型中,绑定不会读取表单,从表单绑定的参数不会绑定。后置操作方法直接与 Request 属性配合使用。MultipartReader 用于读取每个部分。

        现在我们已经添加了服务,我们将在依赖项容器中注册该服务,以便可以使用构造函数将其注入到控制器中。要在依赖项容器中注册服务,我们将在 Program.cs 文件中添加以下代码行。

builder.Services.AddTransient<IStreamFileUploadService, StreamFileUploadLocalService>();

添加控制器

        现在让我们添加用于流文件上传的 MVC 控制器,它将实现获取操作来显示视图和后期操作来处理 ASP.NET Core 中的文件上传。

        我们将在 Controllers\StreamFileUploadController.cs 下添加一个控制器,代码如下:

public class StreamFileUploadController : Controller
{
    readonly IStreamFileUploadService _streamFileUploadService;

    public StreamFileUploadController(IStreamFileUploadService streamFileUploadService)
    {
        _streamFileUploadService = streamFileUploadService;
    }

    [HttpGet]
    public IActionResult Index()
    {
        return View();
    }

    [ActionName("Index")]
    [HttpPost]
    public async Task<IActionResult> SaveFileToPhysicalFolder()
    {
        var boundary = HeaderUtilities.RemoveQuotes(
            MediaTypeHeaderValue.Parse(Request.ContentType).Boundary
        ).Value;
        var reader = new MultipartReader(boundary, Request.Body);
        var section = await reader.ReadNextSectionAsync();
        string response = string.Empty;
        try
        {
            if (await _streamFileUploadService.UploadFile(reader, section))
            {
                ViewBag.Message = "File Upload Successful";
            }
            else
            {
                ViewBag.Message = "File Upload Failed";
            }
        }
        catch (Exception ex)
        {
            // Log ex
            ViewBag.Message = "File Upload Failed";
        }
        return View();
    }
}

        在上面的控制器中,我们通过依赖注入的构造函数注入了 StreamFileUploadService。

        上述后置操作从流中读取文件输入,并且使用流上传的文件在控制器或服务中处理文件之前不会缓冲在服务器的内存或磁盘中。从流中输入的文件只能读取一次。

        创建类型为 Microsoft.AspNetCore.WebUtilities.MultipartReader 的读取器对象,以从多部分数据中读取子部分流。

添加视图

        我们将添加视图以允许用户选择要上传的文件并将其提交到服务器。我们将根据以下代码在 Views\StreamFileUpload\Index.cshtml 下添加一个视图:

<h1>Stream File Upload</h1>
<hr />
<div>
    <form asp-route="StreamFileUpload/Index" enctype="multipart/form-data" method="POST">
        <input type="file" name="file" /> 
        <button type="submit" class="btn btn-primary">Save</button>
    </form>
</div>
@if (ViewBag.Message != null)
{
    <div class="alert" style="margin-top:20px">
        @ViewBag.Message
    </div>

运行并测试代码

        最后,添加所有必需的服务、控制器和视图后,编译并执行代码。执行后导航到路径 /StreamFileUpload/Index,它应该显示如下所示的屏幕:

        在上面的屏幕上,您可以选择要上传的文件,然后单击“上传文件”按钮以在 ASP.NET Core 中执行文件上传。成功提交后,您应该能够在服务器上的 UploadedFiles 文件夹下看到该文件。

文件存储选项

        在我们上面的演示中,我们将文件保存到本地文件系统。不过,在选择文件在 Web 服务器上的存储目标时,还有其他选项可用。文件的常见存储选项如下:

        1、文件系统——在此选项中,文件将保存在本地或网络共享的物理存储上。

        2、数据库— 在此选项中,文件将以 BLOB 或原始数据的形式保存在数据库表的某一列中。

        3、云- 在此选项中,使用云提供商提供的一些文件存储服务将文件保存在云中。

上述选项也支持 ASP.NET Core 中的文件上传。以下是在选择存储选项时应考虑的一些要点:

        1、对于较小的文件上传,与物理存储相比,数据库通常是更快的选择

        2、对于较大的文件上传,物理存储比数据库存储不太经济。

        3、数据库可以成为文件存储的有效选择,因为当我们从数据库中选择记录时,我们也可以与记录一起选择文件数据。

        4、此外,当您将文件存储在数据库中时,您可以将记录与文件数据一起插入作为同一数据库事务的一部分,否则,如果文件位于物理存储中而记录位于数据库中,则如果设计不正确,可能会在记录和文件数据之间产生一些不一致。

        5、当您在数据库中存储较大的文件时,数据库大小会显著增加,从而使数据库备份和恢复成为一个繁重且耗时的过程。

        6、数据库限制可能会对允许存储的文件的最大大小施加一些限制。

        7、对于物理存储,尝试在物理路径上保存文件的应用程序应该对存储位置具有读写权限。

        8、与本地解决方案相比,云存储通常提供更好的稳定性和弹性

        9、与数据库存储相比,物理存储通常不太经济,而且与云数据存储服务相比,数据库存储可能更便宜。

安全注意事项

        在应用程序中提供文件上传功能时,如果您始终保持谨慎,这将有所帮助,因为攻击者可能会尝试通过 ASP.NET Core 中的文件上传功能来利用应用程序。攻击者可能会尝试通过上传受病毒或恶意软件感染的文件来破坏系统,或者可能试图闯入系统以访问网络或服务器。

        以下是您应该考虑的措施,因为这些措施将帮助您阻止攻击者成功破坏系统或侵入系统:

        1、对可上传文件的最大大小进行限制。

        2、如果使用物理存储,则应将上传的文件复制到非系统驱动器。

        3、最好将所有上传文件复制到专用位置,以便更容易对该位置施加访问权限。

        4、当您为磁盘分配读写权限以复制上传的文件时,请确保您最终不会授予执行权限。

        5、您应该将上传的文件复制到与应用程序部署目录不同的目录中。

        6、首先,不要允许用户决定要上传的文件的文件名,或者如果允许用户选择文件名,请确保对文件进行所有验证,以避免出现不必要的关键字或字符。

        7、另外,验证文件扩展名,以便只允许上传允许的文件类型。

        8、对所有上传的文件执行virus\maclware检查。为此,您可以使用第三方API对上传的内容进行病毒/恶意软件扫描。

        9、确保除了客户端验证之外,还要在服务器端对文件执行所有验证。

概括

        我们了解了如何在 ASP.NET Core 应用程序中执行缓冲和流类型的文件上传。在文件大小较小且并发文件提交数量较少的情况下,缓冲方法是更可取的。

        当我们提交大文件或并发文件提交数量较高时,应使用流方法。流类型将有助于减少对服务器内存和磁盘的要求。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/983606.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕业设计SpringBoot+Vue.js制造装备物联及生产管理ERP系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

yoloV5训练visDrone2019-Det无人机视觉下目标检测

一、visDrone2019数据集详解 visDrone2019数据集是无人机视角下最具挑战性的目标检测基准数据集之一&#xff0c;由天津大学机器学习与数据挖掘实验室联合其他研究机构共同构建。该数据集采集自中国14个不同城市&#xff0c;覆盖复杂城市场景、交通枢纽、密集人群等多种环境。…

Unity开发——CanvasGroup组件介绍和应用

CanvasGroup是Unity中用于控制UI的透明度、交互性和渲染顺序的组件。 一、常用属性的解释 1、alpha&#xff1a;控制UI的透明度 类型&#xff1a;float&#xff0c;0.0 ~1.0&#xff0c; 其中 0.0 完全透明&#xff0c;1.0 完全不透明。 通过调整alpha值可以实现UI的淡入淡…

C语言学习笔记-进阶(7)字符串函数3

1. strstr的使用和模拟实现 char * strstr ( const char * str1, const char * str2); Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1. &#xff08;函数返回字符串str2在字符串str1中第⼀次出现的位置&#x…

如何利用数字校园平台提升职业竞争力

现在我们来探讨如何借助数字校园平台来增强自身的职业竞争力。当今之时代&#xff0c;技术与数据堪称热门领域&#xff0c;略懂编程语言及数据分析&#xff0c;于求职之际&#xff0c;实能增添诸多优势&#xff01; 首先&#xff0c;咱们得说说编程语言。现在很多学校都有提供在…

使用 Arduino 的 WiFi 控制机器人

使用 Arduino 的 WiFi 控制机器人 这次我们将使用 Arduino 和 Blynk 应用程序制作一个 Wi-Fi 控制的机器人。这款基于 Arduino 的机器人可以使用任何支持 Wi-Fi 的 Android 智能手机进行无线控制。 为了演示 Wi-Fi 控制机器人,我们使用了一个名为“Blynk”的 Android 移动应…

动态ip和静态ip适用于哪个场景?有何区别

在数字化浪潮席卷全球的今天&#xff0c;IP地址作为网络世界的“门牌号”&#xff0c;其重要性不言而喻。然而&#xff0c;面对动态IP与静态IP这两种截然不同的IP分配方式&#xff0c;许多用户往往感到困惑&#xff1a;它们究竟有何区别&#xff1f;又分别适用于哪些场景呢&…

求最大公约数【C/C++】

大家好啊&#xff0c;欢迎来到本博客( •̀ ω •́ )✧&#xff0c;我将带领大家详细的了解最大公约数的思想与解法。 一、什么是公约数 公约数&#xff0c;也称为公因数&#xff0c;是指两个或多个整数共有的因数。具体来说&#xff0c;如果一个整数能被两个或多个整数整除&…

conda 配置新环境时package will be install 和 package will be download 的区别

install 和 download 的区别 package will be downloaded下的包&#xff1a;这一类显示的是需要从 conda 仓库或其他指定的源下载的软件包。这些软件包通常是 .tar.bz2、.tar.xz 或 .conda 格式的压缩包。这些包会被下载到本地缓存目录&#xff08;通常是 ~/.conda 或 C:\Users…

【2025小黑课堂】计算机二级WPS精选系列20G内容(可下载:真题+预测卷+软件+选择题)

2025年3月全国计算机等级考试即将于3月29日至31日举行。为了帮助广大考生高效备考&#xff0c;小编特意收集并整理了最新版&#xff08;备考2025年3月&#xff09;的小黑课堂计算机二级WPS 电脑题库软件&#xff0c;助力考生在考试中游刃有余&#xff0c;轻松通关&#xff01; …

C++编写Redis客户端

目录 安装redis-plus-plus库 ​编辑 编译Credis客户端 redis的通用命令使用 get/set exists del keys expire /ttl type string类型核心操作 set和get set带有超时时间 set带有NX string带有XX mset mget getrange和setrange incr和decr list类型核心操作…

①EtherCAT转Modbus485RTU网关多路同步高速采集无需编程串口服务器

EtherCAT转Modbus485RTU网关多路同步高速采集无需编程串口服务器https://item.taobao.com/item.htm?ftt&id798036415719 型号 1路总线EC网关 MS-A2-1011 2路总线EC网关 MS-A2-1021 4路总线EC网关 MS-A2-1041 EtherCAT 串口网关 EtherCAT 转 RS485 技术规格 …

C++ Primer 交换操作

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

TDengine 服务无法启动常见原因

taosd 是 TDengine 的核心服务进程&#xff0c;如果无法启动将导致整个数据库无法使用&#xff0c;了解常导致无法启动的原因&#xff0c;可以帮你快速解决问题。 1. 如何查找日志 无法启动的原因记录在日志中&#xff0c;日志文件默认在 /var/log/taos 的 taosdlog.0 或者 t…

一周学会Flask3 Python Web开发-SQLAlchemy连接Mysql数据库

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili app.py下&#xff0c;我们先配置数据库连接&#xff0c;然后写一个简单sql测试。 连接配置&#xff0c;包括用户名&#xff…

【NLP 32、文本匹配任务 —— 深度学习】

大劫大难以后&#xff0c;人不该失去锐气&#xff0c;不该失去热度&#xff0c;你镇定了却依旧燃烧&#xff0c;你平静了却依旧浩荡&#xff0c;致那个从绝望中走出来的自己&#xff0c;共勉 —— 25.1.31 使用深度学习在文本匹配任务上主要有两种方式&#xff1a;① 表示型 ②…

打造智能聊天体验:前端集成 DeepSeek AI 助你快速上手

DeepSeek AI 聊天助手集成指南 先看完整效果&#xff1a; PixPin_2025-02-19_09-15-59 效果图&#xff1a; 目录 项目概述功能特点环境准备项目结构组件详解 ChatContainerChatInputMessageBubbleTypeWriter 核心代码示例使用指南常见问题 项目概述 基于 Vue 3 TypeScrip…

2008-2024年中国手机基站数据/中国移动通信基站数据

2008-2024年中国手机基站数据/中国移动通信基站数据 1、时间&#xff1a;2008-2024年 2、来源&#xff1a;OpenCelliD 3、指标&#xff1a;网络类型、网络代数、移动国家/地区、移动网络代码、区域代码、小区标识、单元标识、坐标经度、坐标纬度、覆盖范围、测量样本数、坐标…

开源订货系统哪个好 三大订货系统源码推荐

在数字化转型加速的今天&#xff0c;企业对订货系统的需求日益增长。一款优质的订货系统源码不仅能提升供应链效率&#xff0c;还能通过二次开发满足个性化业务需求。这里结合 “标准化、易扩展” 两大核心要求&#xff0c;为您精选三款主流订货系统源码&#xff0c;助您快速搭…

实现插入排序

#include <bits/stdc.h> using namespace std; int a[100005],n; void charu() {for(int i1;i<n;i){int keya[i]; //key表示要排序的数字的数值int ji-1; //j表示前面已排序好的数的个数while(j>0&&key<a[j]){a[j1]a[j]; //把a[j]往后挪j--;}a[j1]…