如何使用Flurl上传文件和表单数据?

17

我正在尝试上传一个带有内容主体的文件。是只有使用 PostMultipartAsync 这个方法吗?

在我的 C# 后端代码中,我有如下代码:

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

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

使用 PostMultipartAsync 应该像这样开始:

.PostMultipartAsync((mp) => { 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” 应该包含你想要发布的所有内容,不是吗? - Todd Menier
关于使用Flurl上传文件的“是否是唯一方法”的问题:从技术上讲,不是唯一的方法,但您调用的API或Web服务应该定义所需的格式,无论是multipart/form-data还是其他格式。这是首要需要找出的重要部分。 - Todd Menier
@ToddMenier 你好,关于第一个问题,不是全局的类。我从HttpFile列表中读取。Resource是我的ViewModel类,我只绑定请求字段与该类,它在这里的目的是显示我单独读取其他字段。至于第三部分,这是一个需要multipart/form-data的API,请查看我的更新答案以了解如何使用前端进行操作。 - eestein
你是在询问如何进行一个需要同时上传文件和JSON对象的多部分POST请求吗? - Todd Menier
@ToddMenier 是的 :) - eestein
@ToddMenier 继续说...那个请求是我的网页应用程序今天所做的。我正在我的Xamarin.iOS应用程序中使用flurl。因此,我需要向API发出相同的请求。再次感谢! - eestein
2个回答

35

使用Flurl可以以多种方式将“部分”添加到multipart POST中。我尚未将此添加到文档中,但这里有一个来自问题的示例,基本上演示了每种可能性:

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

1
@guneysus 我认为这不是一个非常常见的情况,Flurl没有直接支持它。你需要自己拆分并执行.AddString("User.Name", "Ahmed")。 (顺便说一句,这种情况与JSON无关。 User={"Name":"Ahmed"}是您将其作为JSON编码值传递的方式,这更为常见。) - Todd Menier
有没有用'PUT'动词的方法来实现这个?我正在使用的API仅支持多部分操作的'PUT'。这是因为API从发送的文件中读取数据,并使用读取的内容进行创建或更新。我将进行PR以添加对其的支持。在这种情况下,我真的想使用Flurl而不是HttpClient,因为Flurl更加简洁。 - Rob L
1
我解决了。谢谢。 - Rob L
1
如果您能展示如何在flurl中断言此多部分调用,我将不胜感激。具体而言,如果请求包含给定部分和内容。 - Valera
我该如何循环遍历我的 Dictionary<string, string> 并将值添加到 AddStringPartsAddString 中? - Rumplin
显示剩余3条评论

1
这是我用过的一种方法。
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(); 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接