2020-03-25 16:31:42 +00:00
|
|
|
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
|
|
|
|
{
|
|
|
|
/// <summary>Payload description headers, describing the content itself.</summary>
|
|
|
|
private const string PayloadContentTypeHeader = "X-Upload-Content-Type";
|
|
|
|
|
|
|
|
/// <summary>Payload description headers, describing the content itself.</summary>
|
|
|
|
private const string PayloadContentLengthHeader = "X-Upload-Content-Length";
|
|
|
|
|
|
|
|
private const int UnknownSize = -1;
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the service.</summary>
|
|
|
|
private HttpClient HttpClient { get; }
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the path of the method (combined with
|
|
|
|
/// <see cref="Google.Apis.Services.IClientService.BaseUri"/>) to produce
|
|
|
|
/// absolute Uri.
|
|
|
|
/// </summary>
|
|
|
|
private string Path { get; }
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the HTTP method of this upload (used to initialize the upload).</summary>
|
|
|
|
private string HttpMethod { get; }
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the stream's Content-Type.</summary>
|
|
|
|
private string ContentType { get; }
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the body of this request.</summary>
|
|
|
|
private FileRequest Body { get; }
|
|
|
|
|
|
|
|
private long _streamLength;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a resumable upload instance with the required parameters.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="contentStream">The stream containing the content to upload.</param>
|
|
|
|
/// <remarks>
|
|
|
|
/// Caller is responsible for maintaining the <paramref name="contentStream"/> open until the upload is
|
|
|
|
/// completed.
|
|
|
|
/// Caller is responsible for closing the <paramref name="contentStream"/>.
|
|
|
|
/// </remarks>
|
|
|
|
public FarmmapsUploader(ConfigurableHttpClient httpClient, Stream contentStream, FileRequest body, string contentType)
|
|
|
|
: 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;
|
2020-03-25 16:49:00 +00:00
|
|
|
|
|
|
|
body.ChunkSize = ChunkSize;
|
2020-03-25 16:31:42 +00:00
|
|
|
Body = body;
|
|
|
|
Path = "api/v1/file";
|
|
|
|
HttpClient = httpClient;
|
|
|
|
HttpMethod = HttpConsts.Post;
|
|
|
|
ContentType = contentType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public override async Task<Uri> 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>Creates a request to initialize a request.</summary>
|
|
|
|
private HttpRequestMessage CreateInitializeRequest()
|
|
|
|
{
|
|
|
|
var builder = new RequestBuilder()
|
|
|
|
{
|
2020-03-25 16:49:00 +00:00
|
|
|
BaseUri = HttpClient.BaseAddress,
|
2020-03-25 16:31:42 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|