【问题标题】:How can I create HttpRequest (in C#) with attached files?如何使用附加文件创建 HttpRequest(在 C# 中)?
【发布时间】:2021-06-29 12:23:05
【问题描述】:

正如标题所说,可以找到大量关于发布到端点的资源(例如来自 JS),但是我如何用文件构造 HttpRequest(在 C# .Net 核心中) ?

我的尝试

var myRequest = new DefaultHttpContext().Request;
myRequest.Form.Files // GET only!

我似乎无法 set 文件集合 (IFormFileCollection),我只能 get 它。

更多背景

这是为了集成测试端点。除了我必须点击该方法,而不是通过 URL 访问它(出于某种原因)。该方法接受HttpRequest 并解析出Form.Files 集合。因此我需要为我的断言添加一些文件。

【问题讨论】:

  • 你为什么要这样做?
  • 对,Files 是只读的。您调用Add 方法将文件添加到集合中...似乎您想要执行WebRequest.Create(url) 之类的操作,而不是获取当前请求...
  • 您希望内容是一个 mime 附件,它被添加到正文并以带有两个破折号的新行开头。请参阅:docs.microsoft.com/en-us/previous-versions/office/developer/…
  • @jdweng 不,甚至没有关闭
  • @DavidG :我的建议没有错。 MIME 是您将文件添加到 HTML 消息的方式。

标签: c# asp.net-core .net-core httprequest integration-testing


【解决方案1】:

您是否已经尝试过这样的事情:

using (var stream = new MemoryStream(fileBytes))
{
    var bla = new DefaultHttpContext().Request;
    bla.Form.Files.Append(new Microsoft.AspNetCore.Http.Internal.FormFile(stream, 0, stream.Length, "file.txt", "file.txt"));
}

【讨论】:

  • 这可能是一个,我不知道 append 方法,因为我从来不需要手动构造这样的请求。非常感谢,将尝试并报告。
  • 我们可能使用不同的版本,但我无权访问Internal,不是一个公认的命名空间。
  • 我相信全名是Microsoft.AspNetCore.Http.FormFile
  • 我正在使用与 Microsoft.NET.Sdk.Functions 一起“发布”的那个,它是 2.1.0(已经很老了)。但你总是可以自己实现 IFormFile,它不是那么大。
【解决方案2】:

您可以通过以下方法实现此目的

public async Task<string> UploadFile(string filePath)
{
    
    if (string.IsNullOrWhiteSpace(filePath))
    {
        throw new ArgumentNullException(nameof(filePath));
    }

    if (!File.Exists(filePath))
    {
        throw new FileNotFoundException($"File [{filePath}] not found.");
    }
    using var form = new MultipartFormDataContent();
    using var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));
    fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
    form.Add(fileContent, "file", Path.GetFileName(filePath));
    form.Add(new StringContent("789"), "userId");
    form.Add(new StringContent("some comments"), "comment");
    form.Add(new StringContent("true"), "isPrimary");

    var response = await _httpClient.PostAsync($"{_url}/api/files", form);
    response.EnsureSuccessStatusCode();
    var responseContent = await response.Content.ReadAsStringAsync();
    var result = JsonSerializer.Deserialize<FileUploadResult>(responseContent);
   
    return result.Guid;
}

这个方法是从一个不错的博客上截取的:https://codeburst.io/upload-download-files-using-httpclient-in-c-f29051dea40c

【讨论】:

    【解决方案3】:

    看起来像这样:

    var context = new DefaultHttpContext();
    var formFiles = new FormFileCollection();
    var formValues = new Dictionary<string, StringValues>() { };
    var formCollection = new FormCollection(formValues, formFiles);
    context.Features.Set<IFormFeature>(new FormFeature(formCollection));
    

    根据您要测试的内容填写 formFiles 和 formValues 变量。这里的关键是将功能设置为您的自定义 FormFeature。这将完全插入 .Form 和 ReadFormAsync 的默认行为

    PS:这是 单元测试 假设您没有尝试将真实文件发送到服务器端,否则 mustafa hassan 的答案有效

    【讨论】:

      猜你喜欢
      • 2022-10-19
      • 1970-01-01
      • 1970-01-01
      • 2017-10-28
      • 2015-12-15
      • 1970-01-01
      • 2017-09-12
      • 2010-09-26
      • 1970-01-01
      相关资源
      最近更新 更多