在 ASP.Net Web Api 2 中使用 PUT 动词上传文件

2023-11-21

我想使用 HTTP PUT 动词公开 ASP.Net Web Api 2 操作来上传文件。这与我们的 REST 模型一致,因为 API 代表远程文件系统(类似于 WebDAV,但确实简化了),因此客户端选择资源名称(因此 PUT 是理想的,POST 不是逻辑选择)。

Web Api 文档描述了如何使用 multipart/form-data 表单上传文件,但没有描述如何使用 PUT 方法来做到这一点。

您将使用什么来测试这样的 API(HTML 多部分表单不允许 PUT 动词)?服务器实现是否类似于中描述的多部分实现Web API 文档(使用MultipartStreamProvider),或者应该看起来像这样:

[HttpPut]
public async Task<HttpResponseMessage> PutFile(string resourcePath)
{
    Stream fileContent = await this.Request.Content.ReadAsStreamAsync();
    bool isNew = await this._storageManager.UploadFile(resourcePath, fileContent);
    if (isNew)
    {
        return this.Request.CreateResponse(HttpStatusCode.Created);
    }
    else
    {
        return this.Request.CreateResponse(HttpStatusCode.OK);
    }
}

经过几次测试后,我作为示例发布的服务器端代码似乎是正确的。这是一个示例,删除了任何身份验证/授权/错误处理代码:

[HttpPut]
[Route(@"api/storage/{*resourcePath?}")]
public async Task<HttpResponseMessage> PutFile(string resourcePath = "")
{
    // Extract data from request
    Stream fileContent = await this.Request.Content.ReadAsStreamAsync();
    MediaTypeHeaderValue contentTypeHeader = this.Request.Content.Headers.ContentType;
    string contentType =
        contentTypeHeader != null ? contentTypeHeader.MediaType : "application/octet-stream";

    // Save the file to the underlying storage
    bool isNew = await this._dal.SaveFile(resourcePath, contentType, fileContent);

    // Return appropriate HTTP status code
    if (isNew)
    {
        return this.Request.CreateResponse(HttpStatusCode.Created);
    }
    else
    {
        return this.Request.CreateResponse(HttpStatusCode.OK);
    }
}

一个简单的控制台应用程序足以测试它(使用 Web Api 客户端库):

using (var fileContent = new FileStream(@"C:\temp\testfile.txt", FileMode.Open))
using (var client = new HttpClient())
{
    var content = new StreamContent(fileContent);
    content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
    client.BaseAddress = new Uri("http://localhost:81");
    HttpResponseMessage response =
        await client.PutAsync(@"/api/storage/testfile.txt", content);
}

2018年5月9日编辑:

如中所述这条评论,如果您计划支持带有扩展名的文件名({filename}.{extension})在不强制客户端附加尾部斜杠的情况下,您需要修改 web.config 以将 IIS 绑定到这些文件类型的 Web api 应用程序,因为默认情况下 IIS 将使用静态文件处理程序来处理看起来像文件名的内容(即最后一个路径段包含点的 URL)。我的system.webServer部分看起来像:

<system.webServer>
    <handlers>
      <!-- Clear all handlers, prevents executing code file extensions or returning any file contents. -->
      <clear />
      <!-- Favicon static handler. -->
      <add name="FaviconStaticFile" path="/favicon.ico" verb="GET" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
      <!-- By default, only map extensionless URLs to ASP.NET -->
      <!-- (the "*." handler mapping is a special syntax that matches extensionless URLs) -->
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
      <!-- API endpoints must handle path segments including a dot -->
      <add name="ExtensionIncludedUrlHandler-Integrated-4.0" path="/api/storage/*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
</system.webServer>

请注意,由于各种限制,某些文件名将无法使用。例如,您不能命名路径段. or ..由于 RFC 要求替换它,Azure 托管服务不允许冒号作为路径段的最后一个字符,并且 IIS 默认情况下禁止使用一组字符。

您可能还想增加 IIS/ASP.NET 文件上传大小限制:

<!-- Path specific settings -->
<location path="api/storage">
  <system.web>
    <httpRuntime maxRequestLength="200000000" />
  </system.web>
  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="200000000" />
      </requestFiltering>
    </security>
    </system.webServer>
</location>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 ASP.Net Web Api 2 中使用 PUT 动词上传文件 的相关文章

  • 路径不是有效的虚拟路径

    下面的方法采用指向 xml 文件的路径 tree LoadContentFile path 我从本地文件系统传递完整路径 或使用Server MapPath 但每次我总是收到此错误 Path 不是有效的虚拟路径 编辑 我正在使用Teleri
  • 运行WPF应用程序时出错

    该应用程序在制作它的计算机上运行良好 但是当我将其复制到另一台相同的操作系统时 它崩溃并显示以下错误 Problem signature Problem Event Name CLR20r3 Problem Signature 01 vpn
  • WriteLine 与类

    我正在制作一个 SchoolApp 程序来学习 C 并且我正在尝试实现以下主要功能 namespace SchoolApp class Program public static void Main string args School s
  • LongListSelector 更改 ItemTemplate

    我想动态改变ItemTemplate of a LongListSelector 我通过将其绑定到 ViewModel 中的属性来做到这一点
  • C++ 将 HashMap 对象返回给 Java

    我有一个 JAVA 调用的 JNI 函数 需要构建并返回一个 HashMap 映射的键是 String 相应的值是 boolean 或 Boolean 任何一个都可以 只要它有效 使用我当前的代码 如下 该字符串已成功添加到返回的映射中 并
  • Unity C# 嵌套 IEnumerator

    在我的代码中 我嵌套了 IEnumerator 方法 如下所示 private IEnumerator PerformRequest string url Doing stuff UnityWebRequest request UnityW
  • 类型或命名空间名称“X”在命名空间“Y”中不存在 - 在 VS 生成的代码中

    这是我遇到过的最奇怪的错误 这个 MVC Web 项目直到今天都运行良好 几周以来还没有任何人对其进行处理 尽管没有任何改变 但现在简单地运行它会导致 命名空间 CMSModels ViewModels 中不存在类型或命名空间名称 Colo
  • cppcheck 找不到包含文件

    cppcheck 甚至找不到标准标头 例如 iostream 有任何想法吗 我正在使用 Ubuntu 11 04 和存储库中的 cppcheck cppcheck 在 Mac 和 Linux 上查找标准包含头确实很糟糕 幸运的是 您可以取消
  • 从express.js 中删除所有标头

    我正在创建一个页面 其中有一些数据可以由另一个设备解析 我曾经使用 php 执行此操作 但现在将其移至 Node js 我需要从页面中删除所有标题 这样我就只有我的输出 此输出是对 GET 请求的响应 此刻我有 HTTP 1 1 200 O
  • 结构体指针运算符猜想(理论)

    结构体指针的使用非常频繁 因此有一个特殊的运算符 gt 下面的表达式是等价的 x y x gt y 将此运算符简单地视为如下定义的预处理器宏是否公平 define x gt x 为什么或者为什么不 或者它从一开始就被编码为运算符 这有何不同
  • 处理多个自动重定向的正确方法是什么?

    我有一个网站 基本上允许客户构建一个包含可配置项目的购物车 用户将选择一个项目 系统会提示他们选择他们想要的第一个选项 然后他们将被发送到第二个步骤 在那里他们选择第二个选项 等等 步骤数和选项数是可变的 因为它们是由客户定义的 通常该项目
  • 如何在不重载“operator()”、“std::less”、“std::greater”的情况下为“std::multiset”提供自定义比较器?

    我想要一个用于以下代码的自定义比较器 但是 我不被允许超载operator std less std greater 我尝试使用 lambda 来实现这一点 但是gcc不允许我使用auto作为非静态成员 还有其他方法可以使这项工作有效吗 i
  • 隐藏 AppBar 中的省略号

    当您在 UWP 应用中创建 AppBar 或 CommandBar 时 控件侧面附近总会隐藏一个省略号 如下所示 我不想在我的应用程序中使用它 但我没有在其中找到任何方法 属性AppBar这会帮助我摆脱它 这应该是可能的 因为许多默认的 W
  • 将 CreateThread 与 lambda 结合使用

    只是试验 但我想知道是否可以使该代码工作 如编译 void main int number 5 DWORD dontThreadOnMe PVOID PVOID data int value int data cout lt lt valu
  • Visual Studio 2019 能否将所需的 DLL 打包到一个小的 .exe 文件中?

    我使用 Visual Studio 2019 使用 C WinAPI 制作了一个 Windows 应用程序 完成后 我构建了它 并在我的计算机上执行 它工作完美 然后我发给我没有Visual Studio的朋友 它说需要 msvcp140d
  • 如何在 Linux 中创建可通过 Screen 应用程序连接的 pty

    我想创建 C C 应用程序 它在 dev xxx 中创建新的 虚拟 设备 并且能够与 屏幕 应用程序连接 例如 循环运行的程序会创建新的 dev ttyABC 然后我将使用 屏幕 dev ttyABC 当我向那里发送一些字符时 应用程序将其
  • 简单的 C# 屏幕共享应用程序

    我希望用 C 创建一个非常基本的屏幕共享应用程序 无需远程控制 我只希望用户能够将他们的屏幕广播到网络服务器 我应该如何实施这个 任何指向正确方向的指针将不胜感激 它不需要很高的 FPS 甚至更新 5 秒左右就足够了 您认为每隔 5 秒上传
  • 使用传输编码分块的 HTTP 响应中的最大块大小是多少?

    The w3 org RFC2616 http www w3 org Protocols rfc2616 rfc2616 sec3 html sec3 6 1似乎没有定义块的最大大小 但是如果没有最大块大小 则没有空间用于块扩展 必须有一个
  • 在 Qt 服务器上验证用户身份

    我正在尝试使用 C QtTcpSocket 为个人项目 多人国际象棋游戏 实现身份验证系统 我的朋友建议了一种验证用户的方法 但我想问是否有更简单或更好的方法 来自 Python 背景 做这个项目主要是为了加深对 C 的理解 我将发布我朋友
  • String.将 CRLF 替换为 '\n'

    我想知道是否有一种方法可以用 n 替换所有 CRLF 实例 有办法实现吗 你尝试过哪些方法不起作用 回车换行的意思回车 http en wikipedia org wiki Carriage return 换行 http en wikipe

随机推荐

  • Java 8 中的 completableFuture 是否可以扩展到多核?

    假设我有一个线程 它调用一堆返回 completablefuture 的方法 并说我将它们全部添加到列表中 最后我这样做了completablefutures allof list size join 现在列表中的 future 可以扩展到
  • viewDidUnload 与 viewDidDisappear

    我不明白什么时候应该实施一些东西viewDidUnload versus viewDidDisappear 两者有什么区别 例如 我想发送一个NSNotification当视图控制器从视图层次结构中删除时 在这两种方法之间 我从哪里发布通知
  • vlc mac python绑定没有视频输出

    我正在使用 vlc python 绑定来播放视频 然后我得到了这些错误 0x3d0c58 main window error corrupt module Applications VLC app Contents MacOS plugin
  • 当我们将“cc”添加到 clobber 列表时,程序集输出中会发生什么

    我读到 如果我们在 clobber 列表中指定 cc 则表明汇编代码修改标志寄存器 编写了一个示例程序来检查添加 cc 和不添加 cc 之间的区别 比较程序集 当我们添加 cc 时没有变化 include
  • 多线程控制台 I/O

    我在多线程应用程序中使用控制台 现在 它只接受输出 printf 等 到目前为止我没有任何问题 然而 我也希望能够支持控制台输入 这就是我的生活变得复杂的地方 预先警告一下 我非常不熟悉使用控制台输入和输出的更复杂的细微差别 我在这个主题上
  • 从数组中读取随机值

    我有一个包含 14 个字符串的数组 我想向用户显示这 14 个字符串 并且不重复 我得到的最接近的是创建一个整数数组并打乱它们的值 然后使用 int 数组中的数字之一作为索引从字符串数组中读取 appDelegate randomRiddl
  • 比较 Pandas Dataframe 行并删除具有重叠日期的行

    我有一个数据框 其中包含从交易策略中获取的交易 交易策略中的逻辑需要更新 以确保如果该策略已经在交易中 则不会进行交易 但这是一个不同的问题 许多先前交易的交易数据从 csv 文件读入数据帧 这是我所拥有的数据的问题 我需要对数据帧进行逐行
  • 判断一棵树是否是另一棵树的子树

    有两个二叉树T1和T2 存储字符数据 允许重复 如何确定 T2 是否是 T1 的子树 T1有数百万个节点 T2有数百个节点 穿越T1 如果当前节点等于T2的根节点 则同时遍历两棵树 T2和T1的当前子树 比较当前节点 如果它们始终相等 则
  • React Native:在 Jest 单元测试中模拟离线设备

    我正在编写一个 React Native 应用程序 并使用 Jest 来对我的代码进行单元测试 我编写了一个函数来检查是否有互联网连接 我知道想要编写它的单元测试 我陷入困境 因为我无法弄清楚如何在单元测试中模拟设备的连接状态 您如何在单元
  • 没有名为 django.core 的模块

    卸载旧 Django 版本后 我已更新到最新的 Django 版本 1 0 2 但是现在当我运行 django admin py 时 出现以下错误 我该如何解决这个问题 Traceback most recent call last Fil
  • 多个(超过2个)数字的最大公约数

    我正在寻找最简单的解决方案来获得多个值的最大公约数 就像是 x gcd array 30 40 35 Should return 5 x gcd array 30 40 Should return 10 你会如何解决这个问题 非常感谢 gc
  • 在服务器端实体框架 5 上生成 Guid?

    我来自 nhibernate 背景 我想知道如何在服务器端自动生成 Guid 而不是在数据库端进行往返 在流利的休眠中 这很简单 Id x gt x Id GeneratedBy GuidComb 如果您想在服务器上生成密钥 只需在代码中执
  • 在应用程序内购买时显示消息“您已经拥有该商品”。在安卓中

    我正在尝试在应用程序内实现 在android中 应用程序内运行完美 但是 当我remove来自设备的应用程序和重新安装它 然后如果我尝试购买 它会显示此消息 product is Managed and in app API Version
  • Android:更改微调器下拉视图

    Im My application I want the below type of Spinner Dropdown view For this type of spinner view I wrote this code ArrayAd
  • 在 C# 中复制 T-SQL DecryptByPassPhrase

    我想要创建一个 C 类来解密使用 T SQL 的 EncryptByPassPhrase 加密的字节数组 是的 我知道我可以在 SQL Server 中解密 但我需要的是能够在数据库层和中间层中同等地加密 解密 据我所知 SQL Serve
  • 为什么 window.showModalDialog 被弃用?用什么代替?

    我正在开发一个 GreaseMonkey 脚本 它使用window showModalDialog 但还没完成 我就发现Firefox 29发出了警告 不推荐使用 window showModalDialog 使用 window open
  • R Shiny 使滑块值动态化

    我有一个下拉选择器和一个滑块刻度 我想用下拉选择器作为数据源来渲染一个图 我已经让这部分工作了 我只是希望滑块的最大值根据选择的数据集进行更改 有什么建议么 server R library shiny shinyServer functi
  • 在 Pyspark 中按列分组并筛选具有最大值的行

    我几乎可以肯定这个问题之前已经被问过 但是通过 stackoverflow 进行搜索没有回答我的问题 不是重复的 2 因为我想要最大值 而不是最频繁的项目 我是 pyspark 的新手 尝试做一些非常简单的事情 我想按 A 列进行分组 然后
  • 如何在 Android 手机上找回已登录的 Google 帐户?

    我正在开发一个 Android 应用程序 我需要检索手机上使用的 Google 帐户 我想为 C2DM 执行此操作 但我不想要求用户输入他 她的 Google 电子邮件帐户 如果他们已经登录 有什么方法可以做到吗 像这样的东西应该有效 Ac
  • 在 ASP.Net Web Api 2 中使用 PUT 动词上传文件

    我想使用 HTTP PUT 动词公开 ASP Net Web Api 2 操作来上传文件 这与我们的 REST 模型一致 因为 API 代表远程文件系统 类似于 WebDAV 但确实简化了 因此客户端选择资源名称 因此 PUT 是理想的 P