mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Fixed range requests and consolidated data download
This commit is contained in:
parent
22c5553d3a
commit
dc76918300
@ -161,7 +161,7 @@ namespace Teknik.Areas.Paste.Controllers
|
|||||||
|
|
||||||
Response.Headers.Add("Content-Disposition", cd.ToString());
|
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||||
|
|
||||||
return new BufferedFileStreamResult("application/octet-stream", async (response) => await ResponseHelper.StreamToOutput(response, true, new AesCounterStream(fileStream, false, keyBytes, ivBytes), contentSize, _config.PasteConfig.ChunkSize), false);
|
return new BufferedFileStreamResult("application/octet-stream", async (response) => await ResponseHelper.StreamToOutput(response, new AesCounterStream(fileStream, false, keyBytes, ivBytes), contentSize, _config.PasteConfig.ChunkSize), false);
|
||||||
default:
|
default:
|
||||||
return View("~/Areas/Paste/Views/Paste/Full.cshtml", model);
|
return View("~/Areas/Paste/Views/Paste/Full.cshtml", model);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ namespace Teknik.Areas.Podcast.Controllers
|
|||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any)]
|
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any, NoStore = false)]
|
||||||
[TrackDownload]
|
[TrackDownload]
|
||||||
public IActionResult Download(int episode, string fileName)
|
public IActionResult Download(int episode, string fileName)
|
||||||
{
|
{
|
||||||
@ -215,7 +215,7 @@ namespace Teknik.Areas.Podcast.Controllers
|
|||||||
// Reset file stream to starting position (or start of range)
|
// Reset file stream to starting position (or start of range)
|
||||||
fileStream.Seek(startByte, SeekOrigin.Begin);
|
fileStream.Seek(startByte, SeekOrigin.Begin);
|
||||||
|
|
||||||
return new BufferedFileStreamResult(contentType, (response) => ResponseHelper.StreamToOutput(response, true, fileStream, (int)length, 4 * 1024), false);
|
return new BufferedFileStreamResult(contentType, (response) => ResponseHelper.StreamToOutput(response, fileStream, (int)length, 4 * 1024), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new StatusCodeResult(StatusCodes.Status404NotFound);
|
return new StatusCodeResult(StatusCodes.Status404NotFound);
|
||||||
|
@ -397,28 +397,7 @@ namespace Teknik.Areas.Upload.Controllers
|
|||||||
// Reset file stream to starting position (or start of range)
|
// Reset file stream to starting position (or start of range)
|
||||||
fileStream.Seek(startByte, SeekOrigin.Begin);
|
fileStream.Seek(startByte, SeekOrigin.Begin);
|
||||||
|
|
||||||
try
|
return DownloadData(url, fileStream, contentType, (int)length, key, iv);
|
||||||
{
|
|
||||||
// If the IV is set, and Key is set, then decrypt it while sending
|
|
||||||
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(iv))
|
|
||||||
{
|
|
||||||
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
|
|
||||||
byte[] ivBytes = Encoding.UTF8.GetBytes(iv);
|
|
||||||
|
|
||||||
var aesStream = new AesCounterStream(fileStream, false, keyBytes, ivBytes);
|
|
||||||
|
|
||||||
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, true, aesStream, (int)length, _config.UploadConfig.ChunkSize), false);
|
|
||||||
}
|
|
||||||
else // Otherwise just send it
|
|
||||||
{
|
|
||||||
// Send the file
|
|
||||||
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, true, fileStream, (int)length, _config.UploadConfig.ChunkSize), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogWarning(ex, "Error in Download: {url}", new { url });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new StatusCodeResult(StatusCodes.Status404NotFound);
|
return new StatusCodeResult(StatusCodes.Status404NotFound);
|
||||||
@ -462,19 +441,7 @@ namespace Teknik.Areas.Upload.Controllers
|
|||||||
|
|
||||||
Response.Headers.Add("Content-Disposition", cd.ToString());
|
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||||
|
|
||||||
// If the IV is set, and Key is set, then decrypt it while sending
|
return DownloadData(upload.Url, fileStream, upload.ContentType, (int)upload.ContentLength, upload.Key, upload.IV);
|
||||||
if (decrypt && !string.IsNullOrEmpty(upload.Key) && !string.IsNullOrEmpty(upload.IV))
|
|
||||||
{
|
|
||||||
byte[] keyBytes = Encoding.UTF8.GetBytes(upload.Key);
|
|
||||||
byte[] ivBytes = Encoding.UTF8.GetBytes(upload.IV);
|
|
||||||
|
|
||||||
return new BufferedFileStreamResult(upload.ContentType, (response) => ResponseHelper.StreamToOutput(response, true, new AesCounterStream(fileStream, false, keyBytes, ivBytes), (int)upload.ContentLength, _config.UploadConfig.ChunkSize), false);
|
|
||||||
}
|
|
||||||
else // Otherwise just send it
|
|
||||||
{
|
|
||||||
// Send the file
|
|
||||||
return new BufferedFileStreamResult(upload.ContentType, (response) => ResponseHelper.StreamToOutput(response, true, fileStream, (int)upload.ContentLength, _config.UploadConfig.ChunkSize), false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json(new { error = new { message = "File Does Not Exist" } });
|
return Json(new { error = new { message = "File Does Not Exist" } });
|
||||||
@ -540,5 +507,33 @@ namespace Teknik.Areas.Upload.Controllers
|
|||||||
}
|
}
|
||||||
return Json(new { error = new { message = "This Upload does not exist" } });
|
return Json(new { error = new { message = "This Upload does not exist" } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IActionResult DownloadData(string url, Stream fileStream, string contentType, int length, string key, string iv)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// If the IV is set, and Key is set, then decrypt it while sending
|
||||||
|
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(iv))
|
||||||
|
{
|
||||||
|
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
|
||||||
|
byte[] ivBytes = Encoding.UTF8.GetBytes(iv);
|
||||||
|
|
||||||
|
var aesStream = new AesCounterStream(fileStream, false, keyBytes, ivBytes);
|
||||||
|
//return File(aesStream, contentType, true);
|
||||||
|
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, aesStream, length, _config.UploadConfig.ChunkSize), false);
|
||||||
|
}
|
||||||
|
else // Otherwise just send it
|
||||||
|
{
|
||||||
|
// Send the file
|
||||||
|
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, fileStream, length, _config.UploadConfig.ChunkSize), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Error in Download: {url}", new { url });
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,10 +54,10 @@ namespace Teknik.Utilities.Cryptography
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CounterModeCryptoTransform : ICryptoTransform
|
public class CounterModeCryptoTransform : ICryptoTransform, IDisposable
|
||||||
{
|
{
|
||||||
private readonly int _BlockSize;
|
private readonly int _BlockSize;
|
||||||
private readonly Memory<byte> _IV;
|
private readonly byte[] _IV;
|
||||||
private readonly byte[] _Counter;
|
private readonly byte[] _Counter;
|
||||||
private readonly byte[] _EncryptedCounter;
|
private readonly byte[] _EncryptedCounter;
|
||||||
private readonly ICryptoTransform _CounterEncryptor;
|
private readonly ICryptoTransform _CounterEncryptor;
|
||||||
@ -103,12 +103,16 @@ namespace Teknik.Utilities.Cryptography
|
|||||||
|
|
||||||
_BlockSize = symmetricAlgorithm.BlockSize;
|
_BlockSize = symmetricAlgorithm.BlockSize;
|
||||||
|
|
||||||
|
// Initialize Counter
|
||||||
|
_Counter = new byte[initialCounter.Length];
|
||||||
|
initialCounter.CopyTo(_Counter, 0);
|
||||||
|
|
||||||
// Initialize the encrypted counter
|
// Initialize the encrypted counter
|
||||||
_EncryptedCounter = new byte[_BlockSize / 8];
|
_EncryptedCounter = new byte[_BlockSize / 8];
|
||||||
|
|
||||||
_IV = iv;
|
// Initialize IV
|
||||||
|
_IV = new byte[iv.Length];
|
||||||
_Counter = initialCounter;
|
iv.CopyTo(_IV, 0);
|
||||||
|
|
||||||
_CounterEncryptor = symmetricAlgorithm.CreateEncryptor(key, iv);
|
_CounterEncryptor = symmetricAlgorithm.CreateEncryptor(key, iv);
|
||||||
|
|
||||||
@ -204,7 +208,7 @@ namespace Teknik.Utilities.Cryptography
|
|||||||
|
|
||||||
public void ResetCounter()
|
public void ResetCounter()
|
||||||
{
|
{
|
||||||
_IV.CopyTo(_Counter);
|
_IV.CopyTo(_Counter, 0);
|
||||||
_Iterations = 0;
|
_Iterations = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ namespace Teknik.Utilities.Cryptography
|
|||||||
int processed = 0;
|
int processed = 0;
|
||||||
|
|
||||||
// Read the data from the stream
|
// Read the data from the stream
|
||||||
int bytesRead = await _Inner.ReadAsync(buffer);
|
int bytesRead = await _Inner.ReadAsync(buffer).ConfigureAwait(false);
|
||||||
if (bytesRead > 0)
|
if (bytesRead > 0)
|
||||||
{
|
{
|
||||||
// Process the read buffer
|
// Process the read buffer
|
||||||
@ -128,21 +128,20 @@ namespace Teknik.Utilities.Cryptography
|
|||||||
if (_Inner != null && CanWrite)
|
if (_Inner != null && CanWrite)
|
||||||
{
|
{
|
||||||
// Process the cipher
|
// Process the cipher
|
||||||
Memory<byte> output = buffer;
|
Span<byte> output = buffer;
|
||||||
|
|
||||||
// Process the buffer
|
// Process the buffer
|
||||||
int processed = _Cipher.TransformBlock(output.Span, offset, count);
|
int processed = _Cipher.TransformBlock(output, offset, count);
|
||||||
|
|
||||||
// Do we have more?
|
// Do we have more?
|
||||||
if (processed < count)
|
if (processed < count)
|
||||||
{
|
{
|
||||||
// Finalize the cipher
|
// Finalize the cipher
|
||||||
var finalProcessed = _Cipher.TransformFinalBlock(output.Span, processed + offset, count);
|
var finalProcessed = _Cipher.TransformFinalBlock(output, processed + offset, count);
|
||||||
if (finalProcessed > 0)
|
if (finalProcessed > 0)
|
||||||
processed += finalProcessed;
|
processed += finalProcessed;
|
||||||
}
|
}
|
||||||
ReadOnlyMemory<byte> readOnlyOutput = buffer;
|
_Inner.Write(output);
|
||||||
_Inner.Write(readOnlyOutput.Span);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,12 +254,6 @@ namespace Teknik.Utilities.Cryptography
|
|||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async ValueTask DisposeAsync()
|
|
||||||
{
|
|
||||||
await _Inner.DisposeAsync();
|
|
||||||
await base.DisposeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SyncCounter()
|
private void SyncCounter()
|
||||||
{
|
{
|
||||||
if (_Cipher != null)
|
if (_Cipher != null)
|
||||||
|
@ -11,8 +11,9 @@ namespace Teknik.Utilities
|
|||||||
{
|
{
|
||||||
public static class ResponseHelper
|
public static class ResponseHelper
|
||||||
{
|
{
|
||||||
public async static Task StreamToOutput(HttpResponse response, bool flush, Stream stream, int length, int chunkSize)
|
public async static Task StreamToOutput(HttpResponse response, Stream stream, int length, int chunkSize)
|
||||||
{
|
{
|
||||||
|
response.RegisterForDisposeAsync(stream);
|
||||||
var bufferSize = chunkSize;
|
var bufferSize = chunkSize;
|
||||||
if (length < chunkSize)
|
if (length < chunkSize)
|
||||||
bufferSize = length;
|
bufferSize = length;
|
||||||
@ -27,11 +28,7 @@ namespace Teknik.Utilities
|
|||||||
{
|
{
|
||||||
await response.Body.WriteAsync(buffer.Slice(0, processedBytes));
|
await response.Body.WriteAsync(buffer.Slice(0, processedBytes));
|
||||||
|
|
||||||
// Flush the response
|
await response.Body.FlushAsync();
|
||||||
if (flush)
|
|
||||||
{
|
|
||||||
//await response.Body.FlushAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (processedBytes > 0);
|
while (processedBytes > 0);
|
||||||
@ -42,10 +39,10 @@ namespace Teknik.Utilities
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
//await response.Body.FlushAsync();
|
await response.Body.FlushAsync();
|
||||||
|
|
||||||
// dispose of file stream
|
// dispose of file stream
|
||||||
stream?.Dispose();
|
//stream?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user