using System;
using System.IO;
using System.Net.Http;
using System.Net.Mime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FarmmapsApi.Models;
using Google.Apis.Http;
using Google.Apis.Json;
using Google.Apis.Requests;
using Google.Apis.Upload;
using Google.Apis.Util;
using Newtonsoft.Json;
namespace FarmmapsApi.Services
{
public class FarmmapsUploader : ResumableUpload
{
/// Payload description headers, describing the content itself.
private const string PayloadContentTypeHeader = "X-Upload-Content-Type";
/// Payload description headers, describing the content itself.
private const string PayloadContentLengthHeader = "X-Upload-Content-Length";
private const int UnknownSize = -1;
/// Gets or sets the service.
private HttpClient HttpClient { get; }
///
/// Gets or sets the path of the method (combined with
/// ) to produce
/// absolute Uri.
///
private string Path { get; }
/// Gets or sets the HTTP method of this upload (used to initialize the upload).
private string HttpMethod { get; }
/// Gets or sets the stream's Content-Type.
private string ContentType { get; }
/// Gets or sets the body of this request.
private FileRequest Body { get; }
private long _streamLength;
///
/// Create a resumable upload instance with the required parameters.
///
/// The stream containing the content to upload.
///
/// Caller is responsible for maintaining the open until the upload is
/// completed.
/// Caller is responsible for closing the .
///
public FarmmapsUploader(ConfigurableHttpClient httpClient, Stream contentStream, FileRequest body, string contentType, string path)
: base(contentStream,
new ResumableUploadOptions
{
HttpClient = httpClient,
Serializer = new NewtonsoftJsonSerializer(),
ServiceName = "FarmMaps"
})
{
httpClient.ThrowIfNull(nameof(httpClient));
contentStream.ThrowIfNull(nameof(contentStream));
_streamLength = ContentStream.CanSeek ? ContentStream.Length : UnknownSize;
var twoMB = 2 * 0x100000;
ChunkSize = twoMB;
body.ChunkSize = ChunkSize;
Body = body;
Path = path;
HttpClient = httpClient;
HttpMethod = HttpConsts.Post;
ContentType = contentType;
}
///
public override async Task InitiateSessionAsync(CancellationToken cancellationToken = default)
{
HttpRequestMessage request = CreateInitializeRequest();
Options?.ModifySessionInitiationRequest?.Invoke(request);
var response = await HttpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
throw await ExceptionForResponseAsync(response).ConfigureAwait(false);
}
return response.Headers.Location;
}
/// Creates a request to initialize a request.
private HttpRequestMessage CreateInitializeRequest()
{
var builder = new RequestBuilder()
{
BaseUri = HttpClient.BaseAddress,
Path = Path,
Method = HttpMethod,
};
HttpRequestMessage request = builder.CreateRequest();
if (ContentType != null)
{
request.Headers.Add(PayloadContentTypeHeader, ContentType);
}
// if the length is unknown at the time of this request, omit "X-Upload-Content-Length" header
if (ContentStream.CanSeek)
{
request.Headers.Add(PayloadContentLengthHeader, _streamLength.ToString());
}
var jsonText = JsonConvert.SerializeObject(Body);
request.Content = new StringContent(jsonText, Encoding.UTF8, MediaTypeNames.Application.Json);
return request;
}
}
}