【问题标题】:How can I upload a file and form data using Flurl?如何使用 Flurl 上传文件和表单数据?
【发布时间】:2016-12-08 15:06:22
【问题描述】:

我正在尝试上传带有正文内容的文件。 PostMultipartAsync 是唯一的方法吗?

在我的 C# 后端代码中,我有这个:

var resource = FormBind<StorageFileResource>();
var file = Request.Files.First().ToPostedFile();

FormBind 从请求中读取数据并填充对象。

通过使用PostMultipartAsync,我知道它应该像这样开始:

.PostMultipartAsync((mp) =&gt; { mp.AddFile(name, stream, name)}),但我不知道如何添加对象。你对此有什么想法吗?

这是我目前的尝试:

public static async Task<T> PostFileAsync<T>(string url, object data, string name, Stream stream, object queryString = null)
    where T : class
{
    return await HandleRequest(async () => queryString != null
        ? await url
            .SetQueryParams(queryString)
            .SetClaimsToken()
            .PostMultipartAsync((mp) => { mp.AddFile(name, stream, name)})
            .ReceiveJson<T>()
        : await url
            .SetClaimsToken()
            .PostMultipartAsync((mp) => mp.AddFile(name, stream, name))
            .ReceiveJson<T>());
}

前端正在发出的当前请求:

【问题讨论】:

  • ToPostedFile 是否返回 System.Web.HttpPostedFile?另外,resource 是什么以及它与这里有什么关系? file 应该包含您要发布的所有内容,不是吗?
  • 另外,关于“它是使用 Flurl 上传文件的唯一方法”:技术上没有,但您调用的 API 或 Web 服务应该定义它所需的格式,无论是 multipart/form-data或者是其他东西。这是首先要找出的重要部分。
  • @ToddMenier 嗨,托德,关于第一个问题,不,这是本地课程。我从HttpFile 的列表中阅读。 Resource 是我的 ViewModel 类,我只是将请求字段与该类绑定,这里的目的是显示我正在单独读取其他字段。至于第 3 部分,它是一个需要 multipart/form-data 的 API,请查看我更新的答案,看看今天使用前端是如何完成的。
  • 你是在问如何做一个需要文件和 JSON 对象的多部分帖子?
  • @ToddMenier 是的 :)

标签: c# flurl


【解决方案1】:

有多种方法可以使用 Flurl 将“部分”添加到多部分 POST。我还没有将它添加到docs,但这里有一个来自issue 的示例,它基本上展示了所有可能性:

var resp = await "http://api.com"
    .PostMultipartAsync(mp => mp
        .AddString("name", "hello!")                // individual string
        .AddStringParts(new {a = 1, b = 2})         // multiple strings
        .AddFile("file1", path1)                    // local file path
        .AddFile("file2", stream, "foo.txt")        // file stream
        .AddJson("json", new { foo = "x" })         // json
        .AddUrlEncoded("urlEnc", new { bar = "y" }) // URL-encoded                      
        .Add(content));                             // any HttpContent

【讨论】:

  • 谢谢!我必须为每个属性使用AddJson,因为我需要在表单的请求正文中使用它,仅使用AddJson("json",data) 对象在json 属性内序列化,在Form 属性内。谢谢你:)
  • 我正在尝试通过AddStringParts 方法发送嵌套属性,但它会生成dynamic.ToString(),这是无效的json。我只需要通过分隔点来展平嵌套属性。 ` new { User = new { Name = "Ahmed" } }` => User.Name="Ahmed"
  • @guneysus 我不认为这是一个非常常见的场景,Flurl 没有直接支持它。你需要自己把它拆开然后做.AddString("User.Name", "Ahmed")。 (附带说明一下,这种情况与 JSON 无关。User={"Name":"Ahmed"} 是您将其作为 JSON 编码值传递的方式,这更为常见。)
  • 我想通了。谢谢。
  • 如果您还可以展示如何在 flurl 中声明这个多部分调用,我将不胜感激。具体来说,如果请求包含给定的部分和内容。
【解决方案2】:

这是一种适合我的方法

var result = await endPointApi
    .AppendPathSegments("api","AppFileManager") 
    .WithOAuthBearerToken(token.AccessToken)
    .PostMultipartAsync(mp => mp
        //.AddFile("UploadFile", @"C:\Users\..\Documents\upload.txt")
        .AddFile("UploadFile", new MemoryStream(data), appFile.FileName)
        .AddStringParts(new 
        { 
            IRN = appFile.IRN,
            TransactionIRN = appFile.TransactionIRN, 
            FileName = appFile.FileName,
            TableName = appFile.TableName,
            FileExtension = appFile.FileExtension,
        })

Web Api 控制器实现(使用 MediatR

[HttpPost]
public async Task<IActionResult> Post([FromForm] AppFileManagerCommands.Upload uploadAttachment)
{
  await mediator.Send(uploadAttachment);
  return NoContent(); 
}

【讨论】:

    猜你喜欢
    • 2018-03-08
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    相关资源
    最近更新 更多