/// <summary> /// Copies the segment of the file to the destination stream. /// </summary> /// <param name="destination">The stream to write the file segment to.</param> /// <param name="filePath">The full disk path to the file.</param> /// <param name="offset">The offset in the file to start at.</param> /// <param name="count">The number of bytes to send, or null to send the remainder of the file.</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> used to abort the transmission.</param> /// <returns></returns> public static async Task SendFileAsync(Stream destination, string filePath, long offset, long?count, CancellationToken cancellationToken) { var fileInfo = new FileInfo(filePath); if (offset < 0 || offset > fileInfo.Length) { throw new ArgumentOutOfRangeException(nameof(offset), offset, string.Empty); } if (count.HasValue && (count.Value < 0 || count.Value > fileInfo.Length - offset)) { throw new ArgumentOutOfRangeException(nameof(count), count, string.Empty); } cancellationToken.ThrowIfCancellationRequested(); int bufferSize = 1024 * 16; var fileStream = new FileStream( filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize: bufferSize, options: FileOptions.Asynchronous | FileOptions.SequentialScan); using (fileStream) { fileStream.Seek(offset, SeekOrigin.Begin); await StreamCopyOperationInternal.CopyToAsync(fileStream, destination, count, bufferSize, cancellationToken); } }
public static async Task SendFile(HttpContext httpContext, string requestPath) { await using var fileStream = new FileStream(requestPath, FileMode.Open, FileAccess.Read, FileShare.Read); GetTransferPosition(httpContext, fileStream.Length, out long startRange, out long endRange); fileStream.Position = startRange; var contentType = ContentType.DEFAULT.FromExtension(requestPath); // 7 * 24 Hour * 60 Min * 60 Sec = 604800 Sec; //httpContext.Response.Headers["Access-Control-Allow-Origin"] = "*"; httpContext.Response.Headers["Date"] = DateTime.Now.ToString("r"); //context.Response.Headers.Add("Last-Modified", File.GetLastWriteTime(requestPath).ToString("r")); httpContext.Response.Headers["Server"] = "HtcSharp"; //context.Response.Headers.Add("Cache-Control", "max-age=604800"); httpContext.Response.ContentType = contentType.ToValue(); httpContext.Response.StatusCode = 200; if (UseGzip(httpContext, fileStream.Length)) { httpContext.Response.Headers["Content-Encoding"] = "gzip"; await using var gzipStream = new GZipStream(httpContext.Response.Body, CompressionLevel.Fastest); await StreamCopyOperationInternal.CopyToAsync(fileStream, gzipStream, endRange, httpContext.RequestAborted); } else { httpContext.Response.ContentLength = endRange - startRange; await StreamCopyOperationInternal.CopyToAsync(fileStream, httpContext.Response.Body, endRange, httpContext.RequestAborted); } }
/// <summary>Asynchronously reads the given number of bytes from the source stream and writes them to another stream, using a specified buffer size.</summary> /// <returns>A task that represents the asynchronous copy operation.</returns> /// <param name="source">The stream from which the contents will be copied.</param> /// <param name="destination">The stream to which the contents of the current stream will be copied.</param> /// <param name="count">The count of bytes to be copied.</param> /// <param name="bufferSize">The size, in bytes, of the buffer. This value must be greater than zero. The default size is 4096.</param> /// <param name="cancel">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param> public static Task CopyToAsync(Stream source, Stream destination, long?count, int bufferSize, CancellationToken cancel) => StreamCopyOperationInternal.CopyToAsync(source, destination, count, bufferSize, cancel);