180 lines
6.4 KiB
C#
180 lines
6.4 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http.Json;
|
|
|
|
namespace DocumentService.Client.Clients;
|
|
|
|
/// <summary>
|
|
/// Base class for all DocumentService HTTP clients.
|
|
/// Provides common HTTP operations and error handling.
|
|
/// </summary>
|
|
/// <remarks>
|
|
///
|
|
/// </remarks>
|
|
/// <param name="HttpClient"></param>
|
|
/// <param name="logger"></param>
|
|
/// <exception cref="ArgumentNullException"></exception>
|
|
public abstract class BaseDocumentClient(HttpClient HttpClient, ILogger logger)
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
protected readonly ILogger Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
|
|
/// <summary>
|
|
/// Sends a multipart/form-data POST with a single file and deserializes the JSON response.
|
|
/// </summary>
|
|
protected async Task<TResponse?> SendMultipartAsync<TResponse>(
|
|
string endpoint,
|
|
Stream fileStream,
|
|
string fileName = "file.pdf",
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
using var content = new MultipartFormDataContent();
|
|
var streamContent = new StreamContent(fileStream);
|
|
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
|
|
content.Add(streamContent, "file", fileName);
|
|
|
|
var response = await HttpClient.PostAsync(endpoint, content, cancellationToken);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
return await response.Content.ReadFromJsonAsync<TResponse>(cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends a multipart/form-data POST with a single file and returns the response as a stream.
|
|
/// </summary>
|
|
protected async Task<Stream> SendMultipartForStreamAsync(
|
|
string endpoint,
|
|
Stream fileStream,
|
|
string fileName = "file.pdf",
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
using var content = new MultipartFormDataContent();
|
|
var streamContent = new StreamContent(fileStream);
|
|
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
|
|
content.Add(streamContent, "file", fileName);
|
|
|
|
var response = await HttpClient.PostAsync(endpoint, content, cancellationToken);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
#if NETFRAMEWORK
|
|
return await response.Content.ReadAsStreamAsync();
|
|
#else
|
|
return await response.Content.ReadAsStreamAsync(cancellationToken);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends a multipart/form-data POST with a single file and returns the raw byte array.
|
|
/// </summary>
|
|
protected async Task<byte[]> SendMultipartForBinaryAsync(
|
|
string endpoint,
|
|
Stream fileStream,
|
|
string fileName = "file.pdf",
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
using var content = new MultipartFormDataContent();
|
|
var streamContent = new StreamContent(fileStream);
|
|
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
|
|
content.Add(streamContent, "file", fileName);
|
|
|
|
var response = await HttpClient.PostAsync(endpoint, content, cancellationToken);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
#if NETFRAMEWORK
|
|
return await response.Content.ReadAsByteArrayAsync();
|
|
#else
|
|
return await response.Content.ReadAsByteArrayAsync(cancellationToken);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends a caller-built <see cref="MultipartFormDataContent"/> and returns the response as a stream.
|
|
/// Use this overload when the multipart body contains more than one file (e.g., merge).
|
|
/// </summary>
|
|
protected async Task<Stream> SendMultipartContentForStreamAsync(
|
|
string endpoint,
|
|
MultipartFormDataContent content,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var response = await HttpClient.PostAsync(endpoint, content, cancellationToken);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
#if NETFRAMEWORK
|
|
return await response.Content.ReadAsStreamAsync();
|
|
#else
|
|
return await response.Content.ReadAsStreamAsync(cancellationToken);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Serializes <paramref name="request"/> as JSON, POSTs it, and deserializes the response.
|
|
/// </summary>
|
|
protected async Task<TResponse?> SendJsonAsync<TRequest, TResponse>(
|
|
string endpoint,
|
|
TRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var response = await HttpClient.PostAsJsonAsync(endpoint, request, cancellationToken);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
return await response.Content.ReadFromJsonAsync<TResponse>(cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Serializes <paramref name="request"/> as JSON, POSTs it, and returns the response as a stream.
|
|
/// </summary>
|
|
protected async Task<Stream> SendJsonForStreamAsync<TRequest>(
|
|
string endpoint,
|
|
TRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var response = await HttpClient.PostAsJsonAsync(endpoint, request, cancellationToken);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
#if NETFRAMEWORK
|
|
return await response.Content.ReadAsStreamAsync();
|
|
#else
|
|
return await response.Content.ReadAsStreamAsync(cancellationToken);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Serializes <paramref name="request"/> as JSON, POSTs it, and returns the raw byte array.
|
|
/// </summary>
|
|
protected async Task<byte[]> SendJsonForBinaryAsync<TRequest>(
|
|
string endpoint,
|
|
TRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var response = await HttpClient.PostAsJsonAsync(endpoint, request, cancellationToken);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
#if NETFRAMEWORK
|
|
return await response.Content.ReadAsByteArrayAsync();
|
|
#else
|
|
return await response.Content.ReadAsByteArrayAsync(cancellationToken);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>Converts a byte array to a Base64 string.</summary>
|
|
protected static string ToBase64(byte[] bytes) => Convert.ToBase64String(bytes);
|
|
|
|
/// <summary>Reads a stream fully into a byte array.</summary>
|
|
protected static async Task<byte[]> StreamToBytesAsync(Stream stream, CancellationToken cancellationToken = default)
|
|
{
|
|
if (stream is MemoryStream ms)
|
|
return ms.ToArray();
|
|
|
|
using var memoryStream = new MemoryStream();
|
|
#if NET8_0
|
|
await stream.CopyToAsync(memoryStream, cancellationToken);
|
|
#else
|
|
await stream.CopyToAsync(memoryStream);
|
|
#endif
|
|
return memoryStream.ToArray();
|
|
}
|
|
}
|