Post multipart/form-data 来自带有 HttpClient 的流的文件
Post multipart/form-data file from stream with HttpClient
问题:是否可以使用 httpclient 将 HttpPostedFileBase(仅在内存中可用,在磁盘上不可用。)post 到另一个端点?
我试过的:
我有以下控制器,我们正在 post 从我们的前端输入一个文件,它绑定到文件参数。
public class HomeController : Controller
{
[System.Web.Http.HttpPost]
public async Task<string> Index(HttpPostedFileBase file)
{
//file is not null here, everything works as it should.
//Here im preparing a multipart/form-data request to my api endpoint
var fileStreamContent = new StreamContent(file.InputStream);
using (var client = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileStreamContent);
var response = await client.PostAsync("http://restapi.dev/api/files/add", formData);
var result = await response.Content.ReadAsStringAsync();
return result;
}
}
}
我需要将这个请求传递给另一个不公开的应用程序(所以我们不能 post 直接从客户端)
该控制器看起来像这样:
[RoutePrefix("api/files")]
public class FilesController : ApiController
{
[HttpPost]
[Route("add")]
public async Task<HttpResponseMessage> Add(HttpPostedFileBase file)
{
//This is the problem, file is always null when I post from my backend.
var files = HttpContext.Current.Request.Files.Count > 0 ? HttpContext.Current.Request.Files[0] : null;
return Request.CreateResponse(HttpStatusCode.OK);
}
}
file
始终为空,files
也是。
我错过了什么?当我将 postman 和 post 直接用于 API 端点时,它起作用了。所以我猜我在 HomeController
?
中做错了什么
您可以使用更新的技术对此进行改进。
在webapi中,你可以这样写一个controller方法:
//[Route("api/Foo")] //maybe?
[HttpPost]
public async Task<HttpResponseMessage> MyResourceProxy(HttpRequestMessage request)
现在您可以接受该请求并重写其 RequestUri
属性:
request.RequestUri = new Uri(blah);
新建一个HttpClient
并转发请求:
HttpClient client = new HttpClient();
//make sure that this fails if it's hung for more than 30 seconds
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
try
{
response = await client.SendAsync(request,
HttpCompletionOption.ResponseHeadersRead,
cts.Token);
}
catch (TaskCanceledException)
{
response = new HttpResponseMessage(HttpStatusCode.GatewayTimeout);
}
确保所有东西都得到处理:
request.RegisterForDispose(new IDisposable[] {request, client, cts, response});
然后 return response
return response;
我添加了一个超时机制,可能不适合您的需要。
问题:是否可以使用 httpclient 将 HttpPostedFileBase(仅在内存中可用,在磁盘上不可用。)post 到另一个端点?
我试过的:
我有以下控制器,我们正在 post 从我们的前端输入一个文件,它绑定到文件参数。
public class HomeController : Controller
{
[System.Web.Http.HttpPost]
public async Task<string> Index(HttpPostedFileBase file)
{
//file is not null here, everything works as it should.
//Here im preparing a multipart/form-data request to my api endpoint
var fileStreamContent = new StreamContent(file.InputStream);
using (var client = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileStreamContent);
var response = await client.PostAsync("http://restapi.dev/api/files/add", formData);
var result = await response.Content.ReadAsStringAsync();
return result;
}
}
}
我需要将这个请求传递给另一个不公开的应用程序(所以我们不能 post 直接从客户端) 该控制器看起来像这样:
[RoutePrefix("api/files")]
public class FilesController : ApiController
{
[HttpPost]
[Route("add")]
public async Task<HttpResponseMessage> Add(HttpPostedFileBase file)
{
//This is the problem, file is always null when I post from my backend.
var files = HttpContext.Current.Request.Files.Count > 0 ? HttpContext.Current.Request.Files[0] : null;
return Request.CreateResponse(HttpStatusCode.OK);
}
}
file
始终为空,files
也是。
我错过了什么?当我将 postman 和 post 直接用于 API 端点时,它起作用了。所以我猜我在 HomeController
?
您可以使用更新的技术对此进行改进。
在webapi中,你可以这样写一个controller方法:
//[Route("api/Foo")] //maybe?
[HttpPost]
public async Task<HttpResponseMessage> MyResourceProxy(HttpRequestMessage request)
现在您可以接受该请求并重写其 RequestUri
属性:
request.RequestUri = new Uri(blah);
新建一个HttpClient
并转发请求:
HttpClient client = new HttpClient();
//make sure that this fails if it's hung for more than 30 seconds
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
try
{
response = await client.SendAsync(request,
HttpCompletionOption.ResponseHeadersRead,
cts.Token);
}
catch (TaskCanceledException)
{
response = new HttpResponseMessage(HttpStatusCode.GatewayTimeout);
}
确保所有东西都得到处理:
request.RegisterForDispose(new IDisposable[] {request, client, cts, response});
然后 return response
return response;
我添加了一个超时机制,可能不适合您的需要。