在 .NET Core 中使用 HttpClient 发送包含附加数据的文件列表
Sending list of files with additional data using HttpClient in .NET Core
我正在使用微服务架构,在API网关中,我收到一个请求,我想将包含List<PictureItemDto> pictures
的请求发送到Attachment Microservice
并存储图片信息.
我在 Gateway
和 Attachment MicroService
中都有这些模型 类:
public class PictureDto
{
public List<PictureItemDto> pictures { get; set; }
}
public class PictureItemDto
{
public string seoFilename { get; set; }
public string altAttribute { get; set; }
public string titleAttribute { get; set; }
public IFormFile file { get; set; }
}
这就是我将数据从 API gateway
发送到 Attachment MicroService
的方式:
public async Task<bool> Create(List<PictureItemDto> postPictures)
{
MultipartFormDataContent formDataContent = new MultipartFormDataContent();
for (int i = 0; i < postPictures.Count; i++)
{
var item = postPictures[i];
formDataContent.Add(new StringContent(item.seoFilename), $"pictures[{i}].seoFilename");
formDataContent.Add(new StringContent(item.altAttribute), $"pictures[{i}].altAttribute");
formDataContent.Add(new StringContent(item.titleAttribute), $"pictures[{i}].titleAttribute");
StreamContent fileContent = new(item.file.OpenReadStream())
{
Headers =
{
ContentLength = item.file.Length,
ContentType = new MediaTypeHeaderValue(item.file.ContentType)
}
};
formDataContent.Add(fileContent, $"pictures[{i}].file", item.file.FileName);
}
var result = await _httpClient.PostAsync($"{_urlsOptions.AttachmentUrl}", formDataContent);
return (result.StatusCode == HttpStatusCode.OK) ? true : false;
}
我的问题是 null
在 CreatePostPictures
操作中接收到数据(此操作在 attachment microservice
中):
[HttpPost("create")]
public async Task<IActionResult> CreatePostPictures([FromForm]PictureDto dto)
{
return Ok();
}
这是我发送的 curl :
curl --location --request POST 'http://localhost:80/api/Post?api-version=1.0' \
--header 'accept: */*' \
--header 'api-version: 1.0' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJrYXZlaEBnbWFpbC5jb20iLCJqdGkiOiJlYjhkZmIyMy0wYTAxLTQzOWEtOWM1NS01Y2NmY2I2NmY3YzgiLCJ1bmlxdWVfbmFtZSI6ImthdmVoQGd' \
--form 'postPictures[0].titleAttribute="titleAttribute"' \
--form 'postPictures[0].seoFilename="seoFilename"' \
--form 'postPictures[0].altAttribute="altAttribute"' \
--form 'postPictures[0].File=@"/F:/Photos/WallPapers Pack 2011/Series 2/1024x768/WP2011.2 1024x768 (8).jpg"' \
--form 'postPictures[1].titleAttribute="titleAttribute1"' \
--form 'postPictures[1].seoFilename="seoFilename1"' \
--form 'postPictures[1].altAttribute="altAttribute1"'
--form 'postPictures[1].File=@"/F:/Photos/WallPapers Pack 2011/Series 2/1024x768/WP2011.2 1024x768 (6).jpg"' \
我终于通过将 IFormFile 转换为 Base64String 并将其转换回 IFormFile 解决了这个问题:
首先我添加两个新的 Properties
到 PictureItemDto
class :
public class PictureItemDto
{
public string seoFilename { get; set; }
public string altAttribute { get; set; }
public string titleAttribute { get; set; }
public IFormFile file { get; set; }
// New
public string Base64File { get; set; }
public string ContentType { get; set; }
}
然后在 API Gateway
从 Request
收到的文件应该转换为 Base64String
public async Task<bool> Create(List<PictureItemDto> postPictures)
{
var i = 0;
foreach (var file in postPictures.Select(f => f.File))
{
if (file.Length > 0)
{
using MemoryStream ms = new();
file.CopyTo(ms);
var fileBytes = ms.ToArray();
postPictures[i].Base64File = Convert.ToBase64String(fileBytes);
postPictures[i].ContentType = file.ContentType;
postPictures[i].File = null;
i++;
}
}
JsonContent content = JsonContent.Create(postPictures);
HttpResponseMessage response = await _httpClient.PostAsync($"{_urlsOptions.AttachmentUrl}{UrlsOptions.Attachment.EntityContentController.CreatePostPictures()}", content);
return (response.StatusCode == HttpStatusCode.OK) ? true : false;
}
然后在 Attachment Microservice
中我接收数据并将其转换回 IFormFile
:
[HttpPost("create")]
public async Task<IActionResult> CreatePostPictures([FromBody] List<PictureItemDto> models)
{
List<IFormFile> formFiles = new List<IFormFile>();
foreach (var item in models)
{
byte[] bytes = Convert.FromBase64String(item.Base64File);
MemoryStream stream = new(bytes);
//item.File = new FormFile(stream, 0, bytes.Length, item.SeoFilename, item.SeoFilename);
item.File = new FormFile(stream, 0, stream.Length, null, item.SeoFilename)
{
Headers = new HeaderDictionary(),
ContentType = item.ContentType
};
}
}
我正在使用微服务架构,在API网关中,我收到一个请求,我想将包含List<PictureItemDto> pictures
的请求发送到Attachment Microservice
并存储图片信息.
我在 Gateway
和 Attachment MicroService
中都有这些模型 类:
public class PictureDto
{
public List<PictureItemDto> pictures { get; set; }
}
public class PictureItemDto
{
public string seoFilename { get; set; }
public string altAttribute { get; set; }
public string titleAttribute { get; set; }
public IFormFile file { get; set; }
}
这就是我将数据从 API gateway
发送到 Attachment MicroService
的方式:
public async Task<bool> Create(List<PictureItemDto> postPictures)
{
MultipartFormDataContent formDataContent = new MultipartFormDataContent();
for (int i = 0; i < postPictures.Count; i++)
{
var item = postPictures[i];
formDataContent.Add(new StringContent(item.seoFilename), $"pictures[{i}].seoFilename");
formDataContent.Add(new StringContent(item.altAttribute), $"pictures[{i}].altAttribute");
formDataContent.Add(new StringContent(item.titleAttribute), $"pictures[{i}].titleAttribute");
StreamContent fileContent = new(item.file.OpenReadStream())
{
Headers =
{
ContentLength = item.file.Length,
ContentType = new MediaTypeHeaderValue(item.file.ContentType)
}
};
formDataContent.Add(fileContent, $"pictures[{i}].file", item.file.FileName);
}
var result = await _httpClient.PostAsync($"{_urlsOptions.AttachmentUrl}", formDataContent);
return (result.StatusCode == HttpStatusCode.OK) ? true : false;
}
我的问题是 null
在 CreatePostPictures
操作中接收到数据(此操作在 attachment microservice
中):
[HttpPost("create")]
public async Task<IActionResult> CreatePostPictures([FromForm]PictureDto dto)
{
return Ok();
}
这是我发送的 curl :
curl --location --request POST 'http://localhost:80/api/Post?api-version=1.0' \
--header 'accept: */*' \
--header 'api-version: 1.0' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJrYXZlaEBnbWFpbC5jb20iLCJqdGkiOiJlYjhkZmIyMy0wYTAxLTQzOWEtOWM1NS01Y2NmY2I2NmY3YzgiLCJ1bmlxdWVfbmFtZSI6ImthdmVoQGd' \
--form 'postPictures[0].titleAttribute="titleAttribute"' \
--form 'postPictures[0].seoFilename="seoFilename"' \
--form 'postPictures[0].altAttribute="altAttribute"' \
--form 'postPictures[0].File=@"/F:/Photos/WallPapers Pack 2011/Series 2/1024x768/WP2011.2 1024x768 (8).jpg"' \
--form 'postPictures[1].titleAttribute="titleAttribute1"' \
--form 'postPictures[1].seoFilename="seoFilename1"' \
--form 'postPictures[1].altAttribute="altAttribute1"'
--form 'postPictures[1].File=@"/F:/Photos/WallPapers Pack 2011/Series 2/1024x768/WP2011.2 1024x768 (6).jpg"' \
我终于通过将 IFormFile 转换为 Base64String 并将其转换回 IFormFile 解决了这个问题:
首先我添加两个新的 Properties
到 PictureItemDto
class :
public class PictureItemDto
{
public string seoFilename { get; set; }
public string altAttribute { get; set; }
public string titleAttribute { get; set; }
public IFormFile file { get; set; }
// New
public string Base64File { get; set; }
public string ContentType { get; set; }
}
然后在 API Gateway
从 Request
收到的文件应该转换为 Base64String
public async Task<bool> Create(List<PictureItemDto> postPictures)
{
var i = 0;
foreach (var file in postPictures.Select(f => f.File))
{
if (file.Length > 0)
{
using MemoryStream ms = new();
file.CopyTo(ms);
var fileBytes = ms.ToArray();
postPictures[i].Base64File = Convert.ToBase64String(fileBytes);
postPictures[i].ContentType = file.ContentType;
postPictures[i].File = null;
i++;
}
}
JsonContent content = JsonContent.Create(postPictures);
HttpResponseMessage response = await _httpClient.PostAsync($"{_urlsOptions.AttachmentUrl}{UrlsOptions.Attachment.EntityContentController.CreatePostPictures()}", content);
return (response.StatusCode == HttpStatusCode.OK) ? true : false;
}
然后在 Attachment Microservice
中我接收数据并将其转换回 IFormFile
:
[HttpPost("create")]
public async Task<IActionResult> CreatePostPictures([FromBody] List<PictureItemDto> models)
{
List<IFormFile> formFiles = new List<IFormFile>();
foreach (var item in models)
{
byte[] bytes = Convert.FromBase64String(item.Base64File);
MemoryStream stream = new(bytes);
//item.File = new FormFile(stream, 0, bytes.Length, item.SeoFilename, item.SeoFilename);
item.File = new FormFile(stream, 0, stream.Length, null, item.SeoFilename)
{
Headers = new HeaderDictionary(),
ContentType = item.ContentType
};
}
}