目录

介绍

问题

解决方案

秘密调味料成分1:IFormFile

秘密调味料成分2:IFormFile参数名称

秘密调味料成分#3:FromForm参数属性

秘密调味料成分4:使用表单元素实例化FormData

源代码

客户端

服务器端

CORS

控制器代码

运行代码


  • 下载演示-4.1 KB

介绍

这个上周末,我可能花了6到7个小时来弄清楚如何将文档上载到ASP.NET Core应用程序。尽管有很多示例,但它们并不能满足我的要求,更糟糕的是,还需要一定数量的魔咒,而实际上却没有人花时间去解释。我的意思是没人。我在StackOverflow上发现了一个模糊的响应,它导致了一个问题的解决,另一个问题在Mozilla的FormData站点上。数小时后,“为什么这在Postman中起作用,但在我简单的网站上却不起作用?” 我终于有了一个可行的解决方案。

因此,这篇简短的文章的重点是描述神奇的咒语,这样您就不必经历我的痛苦。也许这对您来说很明显,但是直到现在,实际的可行解决方案还是不存在。

那我的问题是什么?你到底怎么了,马克?

问题

上载文档的常用方法是使用form标签和一个附带的submit按钮。该form标签需要一个带有指向上载终结点的URL的action属性。

为什么不?因为我不想对action属性大惊小怪,而我想使用包装在Promise中的XMLHttpRequest,所以我可以处理响应(在我的例子中,就是上载文档的ID)并捕获异常。此外,标准表单提交会执行重定向,尽管可以通过返回NoContent()来停止重定向,但这是一个令人毛骨悚然的麻烦。当然,您不需要“提交按钮,可以有一个单独的按钮进行调用form.submit(),这也很棒。除了我还想添加不一定是form数据包一部分的键值对,是的,我在那里发现的纠缠涉及隐藏input元素或创建整个form元素及其子元素。

解决方案

一旦弄清了秘密的调味料,解决方案当然很简单。

秘密调味料成分1:IFormFile

因此,.NET Core具有此接口IFormFile,您可以使用该接口将文档流式传输到客户端。但是您不能随便写这样的端点:

public async Task<object> UploadDocument(IFormFile fileToUpload)

秘密调味料成分2:IFormFile参数名称

参数名称必须与HTML 中的name属性值匹配!因此,如果您的HTML看起来像这样:

<input type="file" name="file" />

您的端点必须用file作参数名称:

public async Task<object> UploadDocument(IFormFile file)

“file”与“file”匹配。

您还可以执行以下操作:

public async Task<object> UploadDocument(DocumentUpload docInfo)

而在类DocumentUpload上你有这个:

public class DocumentUpload
{public IFormFile File { get; set; }
}

在此,“File”与“file”匹配。

多个文件也有不同的变体,如List<IFormFile>也被支持。

秘密调味料成分#3:FromForm参数属性

上面的例子不起作用!那是因为我们需要C#属性FromForm,所以这是您正确编写端点(使用类版本)的方式:

public async Task<object> UploadDocument([FromForm] DocumentUpload docInfo)

秘密调味料成分4:使用表单元素实例化FormData

因此,在客户端,我们需要这样做:

let formData = new FormData(form);

form来自这样的代码:document.getElementById("uploadForm");

烦人的是,我遇到了许多例子,人们说这行得通:

let formData = new FormData();
formData.append("file", valueFromInputElement);

这行不通!!!

源代码

因此,这是完整的源代码。

客户端

<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><title>Upload Demo</title>
</head>
<body><style>html.wait, html.wait * {cursor: wait !important;}</style><form id="uploadForm"><div><input type="file" name="file" /></div><div style="margin-top: 10px"><input name="description" placeholder="Description" /></div></form><button onclick="doUpload();" style="margin-top:10px">Upload</button><script>function doUpload() {let form = document.getElementById("uploadForm");Upload("http://localhost:60192/UploadDocument", form, { clientDate: Date() }).then(xhr => alert(xhr.response)).catch(xhr => alert(xhr.statusText));}async function Upload(url, form, extraData) {waitCursor();let xhr = new XMLHttpRequest();return new Promise((resolve, reject) => {xhr.onreadystatechange = () => {if (xhr.readyState == 4) {if (xhr.status >= 200 && xhr.status < 300) {readyCursor();resolve(xhr);} else {readyCursor();reject(xhr);}}};xhr.open("POST", url, true);let formData = new FormData(form);Object.entries(extraData).forEach(([key, value]) => formData.append(key, value));xhr.send(formData);});}function waitCursor() {document.getElementsByTagName("html")[0].classList.add("wait");}function readyCursor() {document.getElementsByTagName("html")[0].classList.remove("wait");}</script>
</body>
</html>

注意事项:

  1. 我已经硬编码"http://localhost:60192/UploadDocument",您可能需要更改端口。
  2. 请注意formData.append(key, value));,这是我要添加不属于form的键/值对的地方。
  3. 没有“提交按钮,而是有一个单独的Upload按钮。

就像我说的那样,简单!

服务器端

我是在VS2019中编写的代码,因此我们使用的是.NET Core 3.1,因此让我们先介绍一些调整。

CORS

必须添加允许跨域发布的功能,因为ASP.NET Core服务器不为该页面提供服务,我只是将其直接加载到Chrome中。因此,请求的“来源”不是来自“服务器”。在Startup类中,我添加了AddCors服务。

public void ConfigureServices(IServiceCollection services)
{services.AddControllers();services.AddCors(options => {options.AddPolicy("CorsPolicy",builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());});
}

并将其应用于:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseCors("CorsPolicy");

其必须在app调用之前完成。说真的,我阅读了有关中间件管道的说明,但是我必须说,WTF?为什么会有初始化顺序问题?

控制器代码

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;namespace UploadDemo.Controllers
{public class DocumentUpload{public string Description { get; set; }public IFormFile File { get; set; }public string ClientDate { get; set; }}[ApiController][Route("")]                                                     public class UploadController : ControllerBase{public UploadController(){}[HttpGet]public ActionResult<string> Hello(){return "Hello World!";}[HttpPost][Route("UploadDocument")]public async Task<object> UploadDocument([FromForm] DocumentUpload docInfo){IFormFile iff = docInfo.File;string fn = iff.FileName;var tempFilename = $@"c:\temp\{fn}";using (var fileStream = new FileStream(tempFilename, FileMode.Create)){await iff.CopyToAsync(fileStream);}return Ok($"File {fn} uploaded.  Description = {docInfo.Description} on {docInfo.ClientDate}");}}
}

注意事项:

  1. 请注意,控制器路由是""因为我不在乎URL中的路径片段。
  2. 我假设您有c:\temp文件夹。毕竟,这是一个演示!

运行代码

运行ASP.NET Core应用程序。它将启动一个浏览器实例:

任何提示都不要关闭它,只是忽略它。

接下来,打开项目文件夹中的“index.html”文件,您应该看到:

选择一个文件,输入描述,然后单击“Upload”按钮,您应该会看到如下所示的警报——当然,响应会有所不同,因为您输入的内容与我不同:

您应该在temp文件夹中注意到您上传的文件:

当然不是那个文件。但是,在找出所有秘密调味料之后,我几乎看起来像这样!

如何在ASP.NET Core中上传文档相关推荐

  1. 如何在ASP.NET Core中上传超大文件

    HTML部分 <%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx. ...

  2. sharepoint 2016 学习系列篇(21)-文档库应用篇-(3)在文档库中上传文档和下载文档

    在文档库中,上传文档到文档库中,有一下几种方式: 第一种,通过文档库页面,点击上载: 点击"浏览",选择需要上载的文件,点击确定 第二种,通过文档库页面,拖文档的方式上载: 在电脑 ...

  3. 在 ASP.NET Core 中上传文件

    简介 文件上传是指将媒体文件(本地文件或网络文件)从客户端上传至服务器存储.ASP.NET Core 支持使用缓冲的模型绑定(针对较小文件)和无缓冲的流式传输(针对较大文件)上传一个或多个文件.缓冲和 ...

  4. asp.net core中上传文件的解决方案

    上传是经常使用的功能,每遇到一个新项目,频繁写重复代码不是什么好事,推荐一个上传类库,仅通过配置文件,即可拥有上传功能和下载控制,RsCode.Storage是专门解决上传这个问题的.它分两个版本:本 ...

  5. ASP.NET Core 上传文件 图片上传

    在 ASP.NET Core 中上传文件 vs2019 选择文件后,调试停止问题 工具 -> 选项 -> 项目和解决方案 -> Web项目 -> 浏览器窗口关闭时停止调试器(s ...

  6. 如何在ASP.NET Core中使用Azure Service Bus Queue

    原文:USING AZURE SERVICE BUS QUEUES WITH ASP.NET CORE SERVICES 作者:damienbod[1] 译文:如何在ASP.NET Core中使用Az ...

  7. 如何在ASP.NET Core中使用JSON Patch

    原文: JSON Patch With ASP.NET Core 作者:.NET Core Tutorials 译文:如何在ASP.NET Core中使用JSON Patch 地址:https://w ...

  8. 如何在ASP.NET Core中编写自定义日志记录提供程序

    目录 介绍 如何实现所需的接口 基础类和附件 FileLoggerProvider具体类及其附件 1. ConfigureLogging() 2. appsettings.json文件 介绍 源代码可 ...

  9. asp英语是什么意思_如何在ASP.NET Core中使用JSON Patch

    原文: JSON Patch With ASP.NET Core 作者:.NET Core Tutorials 译文:如何在ASP.NET Core中使用JSON Patch 地址:https://w ...

最新文章

  1. WHAT THE DATA SAYS ABOUT KUBERNETES DEPLOYMENT PATTERNS
  2. 为什么你闻不到自己胳肢窝的味道?
  3. Qt笔记-Q_UNUSED解决编译器unused paramenter告警
  4. Bootstrap基本使用
  5. error LNK2001: 无法解析的外部符号unresolved external symbol __imp__JNI_CreateJavaVM@12
  6. xticks函数--Matplotlib
  7. 数学建模:层次分析法
  8. 测试开发面试题汇总(自用)
  9. 概率逗号分号_概率里面的逗号
  10. 广X斜Y-1顶岗纪实
  11. Team Tic Tac Toe
  12. 数据嗨客 | 第6期:不平衡数据处理
  13. git push 报错 error: failed to push some refs to ‘git@xxx/xx.git‘
  14. 如何查询电脑本机出厂序列号
  15. html图片用什么软件打开,.svg是什么文件 用什么软件打开
  16. 内部存储器——①静态存储器
  17. html语言怎么在虚线中加字,html – 用CSS添加虚线spacer / infill
  18. A段架构设计_隽语集(IT+設計思考_1801)
  19. BUUCTF栈迁移ciscn_2019_es_2
  20. 视频剪辑必备的6个免费素材库~

热门文章

  1. oracle视频教程 任务,Oracle基础教程(两位专家手把手教你完成各种常见任务)
  2. 一稿过的Banner模板素材!做电商的你一定需要
  3. UI图标设计素材|风格多样的图标
  4. 传统的世界的中国风吉祥纹样海报这样设计。
  5. UI素材模板|网站后台管理的表单可临摹优秀模板
  6. 编程常用英语词汇 | GitHub
  7. CI/CD(持续集成构建/持续交付):如何测试/集成/交付项目代码?(Jenkins,TravisCI)
  8. RabbitMQ架构
  9. 【笔记】具有O-DU和O-RU的eNB / gNB架构
  10. 一周文章导读:在线试用 Linux 系统;Shell实践;VFS;Makefile陷阱;Shell陷阱