/// <summary> /// Initializes a new instance of the <see cref="FileUploadProvider"/> <see langword="class"/>. /// </summary> /// <param name="ticket">The value of <see cref="Ticket"/>.</param> /// <param name="requireSynchronousIO">The value of <see cref="requireSynchronousIO"/></param> public FileUploadProvider(FileTicketResponse ticket, bool requireSynchronousIO) { Ticket = ticket ?? throw new ArgumentNullException(nameof(ticket)); ticketExpiryCts = new CancellationTokenSource(); taskCompletionSource = new TaskCompletionSource <Stream>(); completionTcs = new TaskCompletionSource <object>(); this.requireSynchronousIO = requireSynchronousIO; }
public async Task <IActionResult> Download([Required, FromQuery] string ticket, CancellationToken cancellationToken) { if (ticket == null) { return(BadRequest(new ErrorMessageResponse(ErrorCode.ModelValidationFailure))); } var streamAccept = new MediaTypeHeaderValue(MediaTypeNames.Application.Octet); if (!Request.GetTypedHeaders().Accept.Any(x => streamAccept.IsSubsetOf(x))) { return(StatusCode(HttpStatusCode.NotAcceptable, new ErrorMessageResponse(ErrorCode.BadHeaders) { AdditionalData = $"File downloads must accept both {MediaTypeNames.Application.Octet} and {MediaTypeNames.Application.Json}!" })); } var fileTicketResult = new FileTicketResponse { FileTicket = ticket }; var tuple = await fileTransferService.RetrieveDownloadStream(fileTicketResult, cancellationToken).ConfigureAwait(false); var stream = tuple.Item1; try { if (tuple.Item2 != null) { return(Conflict(tuple.Item2)); } if (stream == null) { return(Gone()); } return(new LimitedFileStreamResult(stream)); } catch { stream.Dispose(); throw; } }
/// <inheritdoc /> public async Task <ErrorMessageResponse> SetUploadStream(FileTicketResponse ticket, Stream stream, CancellationToken cancellationToken) { if (ticket == null) { throw new ArgumentNullException(nameof(ticket)); } FileUploadProvider uploadProvider; lock (uploadTickets) { if (!uploadTickets.TryGetValue(ticket.FileTicket, out uploadProvider)) { logger.LogTrace("Upload ticket {0} not found!", ticket.FileTicket); return(new ErrorMessageResponse(ErrorCode.ResourceNotPresent)); } uploadTickets.Remove(ticket.FileTicket); } return(await uploadProvider.Completion(stream, cancellationToken).ConfigureAwait(false)); }
public async Task <IActionResult> Upload([Required, FromQuery] string ticket, CancellationToken cancellationToken) { if (ticket == null) { return(BadRequest(new ErrorMessageResponse(ErrorCode.ModelValidationFailure))); } var fileTicketResult = new FileTicketResponse { FileTicket = ticket }; var result = await fileTransferService.SetUploadStream(fileTicketResult, Request.Body, cancellationToken).ConfigureAwait(false); if (result != null) { return(result.ErrorCode == ErrorCode.ResourceNotPresent ? Gone() : Conflict(result)); } return(NoContent()); }
/// <inheritdoc /> public async Task <Tuple <FileStream, ErrorMessageResponse> > RetrieveDownloadStream(FileTicketResponse ticket, CancellationToken cancellationToken) { if (ticket == null) { throw new ArgumentNullException(nameof(ticket)); } FileDownloadProvider downloadProvider; lock (downloadTickets) { if (!downloadTickets.TryGetValue(ticket.FileTicket, out downloadProvider)) { logger.LogTrace("Download ticket {0} not found!", ticket.FileTicket); return(Tuple.Create <FileStream, ErrorMessageResponse>(null, null)); } downloadTickets.Remove(ticket.FileTicket); } var errorCode = downloadProvider.ActivationCallback(); if (errorCode.HasValue) { logger.LogDebug("Download ticket {0} failed activation!", ticket.FileTicket); return(Tuple.Create <FileStream, ErrorMessageResponse>(null, new ErrorMessageResponse(errorCode.Value))); } FileStream stream; try { if (downloadProvider.FileStreamProvider != null) { stream = await downloadProvider.FileStreamProvider(cancellationToken).ConfigureAwait(false); } else { stream = ioManager.GetFileStream(downloadProvider.FilePath, downloadProvider.ShareWrite); } } catch (IOException ex) { return(Tuple.Create <FileStream, ErrorMessageResponse>( null, new ErrorMessageResponse(ErrorCode.IOError) { AdditionalData = ex.ToString() })); } try { logger.LogTrace("Ticket {0} downloading...", ticket.FileTicket); return(Tuple.Create <FileStream, ErrorMessageResponse>(stream, null)); } catch { stream.Dispose(); throw; } }