将上传文件从 Api 修改为 Api
Refit upload file from Api to Api
我正在尝试通过改装将图像从一个 Asp 网络核心后端上传到另一个。
await _repository.UploadImageAsync(userId,
new StreamPart(file.OpenReadStream(), file.FileName, file.ContentType), extension);
Api
[Put("/image/{userId}")]
Task<Guid> UploadImageAsync(Guid userId, StreamPart stream, string extension);
接收控制器
[HttpPut("image/{userId}")]
public async Task<IActionResult> UploadImageAsync([FromRoute] Guid userId, StreamPart stream, string extension)
{
return await RunAsync(async () =>
{
var id = await _userImageManager.UploadImageAsync(userId, stream.Value, extension);
return Ok(id);
});
}
一旦我 运行 我得到以下异常:
Newtonsoft.Json.JsonSerializationException: Error getting value from 'ReadTimeout' on 'Microsoft.AspNetCore.Http.ReferenceReadStream'.
---> System.InvalidOperationException: Timeouts are not supported on this stream.
at System.IO.Stream.get_ReadTimeout()
at lambda_method(Closure , Object )
at Newtonsoft.Json.Serialization.ExpressionValueProvider.GetValue(Object target)
--- End of inner exception stack trace ---
at Newtonsoft.Json.Serialization.ExpressionValueProvider.GetValue(Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, JsonSerializerSettings settings)
at Refit.JsonContentSerializer.SerializeAsync[T](T item) in d:\a\s\Refit\JsonContentSerializer.cs:line 34
at Refit.RequestBuilderImplementation.<>c__DisplayClass17_0.<<BuildRequestFactoryForMethod>b__0>d.MoveNext() in d:\a\s\Refit\RequestBuilderImplementation.cs:line 546
--- End of stack trace from previous location where exception was thrown ---
at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in d:\a\s\Refit\RequestBuilderImplementation.cs:line 243
我尝试按照 描述的方式进行操作,但没有成功。我做错了什么吗?
编辑
根据@TomO 的回答,我编辑了我的代码,但对于 stream
:
我仍然得到 null
Api1(发送部分给Api2):
public async Task<Guid> UploadImageAsync(Guid userId, IFormFile file)
{
...
var stream = file.OpenReadStream();
var streamPart = new StreamPart(stream, file.FileName, file.ContentType);
var response = await _repository.UploadImageAsync(userId,
streamPart, extension);
...
}
Api 2(接收方):
[HttpPost("image/{userId}")]
public async Task<IActionResult> UploadImageAsync([FromRoute] Guid userId, string description, IFormFile stream, string extension)
{
...
}
改装 Api:
[Multipart]
[Post("/image/{userId}")]
Task<Guid> UploadImageAsync(Guid userId, [AliasAs("Description")] string description, [AliasAs("File")] StreamPart stream, string extension);
我认为文档(以及问题中链接的解决方案)提供了很好的指导。但无论如何,这就是我要做的事情:
接收API端点:
[HttpPost]
[Route("{*filePath:regex(^.*\.[[^\\/]]+[[A-Za-z0-9]]$)}")]
public async Task<IActionResult> AddFile([FromRoute] AddFileRequest request,
[FromForm] AddFileRequestDetails body,
CancellationToken cancellationToken)
以及对应的改装客户端调用:
[Multipart]
[Post("/{**filePath}")]
Task AddFile(string filePath, [AliasAs("Description")] string description, [AliasAs("File")] StreamPart filepart);
这里重要的是Form主体的所有成员属性(不包括文件)都必须用"AliasAs"属性修饰。
发送方调用:
System.IO.Stream FileStream = request.File.OpenReadStream();
StreamPart sp = new StreamPart(FileStream, request.FileName);
try
{
await _filesClient.AddFile(request.FilePath, request.Description, sp);
}
catch (ApiException ae)
{
...
throw new Exception("Refit FileClient API Exception", ae);
}
希望这对下一个人有帮助...
我正在尝试通过改装将图像从一个 Asp 网络核心后端上传到另一个。
await _repository.UploadImageAsync(userId,
new StreamPart(file.OpenReadStream(), file.FileName, file.ContentType), extension);
Api
[Put("/image/{userId}")]
Task<Guid> UploadImageAsync(Guid userId, StreamPart stream, string extension);
接收控制器
[HttpPut("image/{userId}")]
public async Task<IActionResult> UploadImageAsync([FromRoute] Guid userId, StreamPart stream, string extension)
{
return await RunAsync(async () =>
{
var id = await _userImageManager.UploadImageAsync(userId, stream.Value, extension);
return Ok(id);
});
}
一旦我 运行 我得到以下异常:
Newtonsoft.Json.JsonSerializationException: Error getting value from 'ReadTimeout' on 'Microsoft.AspNetCore.Http.ReferenceReadStream'.
---> System.InvalidOperationException: Timeouts are not supported on this stream.
at System.IO.Stream.get_ReadTimeout()
at lambda_method(Closure , Object )
at Newtonsoft.Json.Serialization.ExpressionValueProvider.GetValue(Object target)
--- End of inner exception stack trace ---
at Newtonsoft.Json.Serialization.ExpressionValueProvider.GetValue(Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, JsonSerializerSettings settings)
at Refit.JsonContentSerializer.SerializeAsync[T](T item) in d:\a\s\Refit\JsonContentSerializer.cs:line 34
at Refit.RequestBuilderImplementation.<>c__DisplayClass17_0.<<BuildRequestFactoryForMethod>b__0>d.MoveNext() in d:\a\s\Refit\RequestBuilderImplementation.cs:line 546
--- End of stack trace from previous location where exception was thrown ---
at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in d:\a\s\Refit\RequestBuilderImplementation.cs:line 243
我尝试按照
编辑
根据@TomO 的回答,我编辑了我的代码,但对于 stream
:
Api1(发送部分给Api2):
public async Task<Guid> UploadImageAsync(Guid userId, IFormFile file)
{
...
var stream = file.OpenReadStream();
var streamPart = new StreamPart(stream, file.FileName, file.ContentType);
var response = await _repository.UploadImageAsync(userId,
streamPart, extension);
...
}
Api 2(接收方):
[HttpPost("image/{userId}")]
public async Task<IActionResult> UploadImageAsync([FromRoute] Guid userId, string description, IFormFile stream, string extension)
{
...
}
改装 Api:
[Multipart]
[Post("/image/{userId}")]
Task<Guid> UploadImageAsync(Guid userId, [AliasAs("Description")] string description, [AliasAs("File")] StreamPart stream, string extension);
我认为文档(以及问题中链接的解决方案)提供了很好的指导。但无论如何,这就是我要做的事情:
接收API端点:
[HttpPost]
[Route("{*filePath:regex(^.*\.[[^\\/]]+[[A-Za-z0-9]]$)}")]
public async Task<IActionResult> AddFile([FromRoute] AddFileRequest request,
[FromForm] AddFileRequestDetails body,
CancellationToken cancellationToken)
以及对应的改装客户端调用:
[Multipart]
[Post("/{**filePath}")]
Task AddFile(string filePath, [AliasAs("Description")] string description, [AliasAs("File")] StreamPart filepart);
这里重要的是Form主体的所有成员属性(不包括文件)都必须用"AliasAs"属性修饰。
发送方调用:
System.IO.Stream FileStream = request.File.OpenReadStream();
StreamPart sp = new StreamPart(FileStream, request.FileName);
try
{
await _filesClient.AddFile(request.FilePath, request.Description, sp);
}
catch (ApiException ae)
{
...
throw new Exception("Refit FileClient API Exception", ae);
}
希望这对下一个人有帮助...