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; } } }