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());
|
||||
|
||||
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:
|
||||
return View("~/Areas/Paste/Views/Paste/Full.cshtml", model);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ namespace Teknik.Areas.Podcast.Controllers
|
||||
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any)]
|
||||
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any, NoStore = false)]
|
||||
[TrackDownload]
|
||||
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)
|
||||
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);
|
||||
|
@ -397,28 +397,7 @@ namespace Teknik.Areas.Upload.Controllers
|
||||
// Reset file stream to starting position (or start of range)
|
||||
fileStream.Seek(startByte, SeekOrigin.Begin);
|
||||
|
||||
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 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 DownloadData(url, fileStream, contentType, (int)length, key, iv);
|
||||
}
|
||||
}
|
||||
return new StatusCodeResult(StatusCodes.Status404NotFound);
|
||||
@ -462,19 +441,7 @@ namespace Teknik.Areas.Upload.Controllers
|
||||
|
||||
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||
|
||||
// If the IV is set, and Key is set, then decrypt it while sending
|
||||
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 DownloadData(upload.Url, fileStream, upload.ContentType, (int)upload.ContentLength, upload.Key, upload.IV);
|
||||
}
|
||||
}
|
||||
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" } });
|
||||
}
|
||||
|
||||
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 Memory<byte> _IV;
|
||||
private readonly byte[] _IV;
|
||||
private readonly byte[] _Counter;
|
||||
private readonly byte[] _EncryptedCounter;
|
||||
private readonly ICryptoTransform _CounterEncryptor;
|
||||
@ -103,13 +103,17 @@ namespace Teknik.Utilities.Cryptography
|
||||
|
||||
_BlockSize = symmetricAlgorithm.BlockSize;
|
||||
|
||||
// Initialize Counter
|
||||
_Counter = new byte[initialCounter.Length];
|
||||
initialCounter.CopyTo(_Counter, 0);
|
||||
|
||||
// Initialize the encrypted counter
|
||||
_EncryptedCounter = new byte[_BlockSize / 8];
|
||||
|
||||
_IV = iv;
|
||||
// Initialize IV
|
||||
_IV = new byte[iv.Length];
|
||||
iv.CopyTo(_IV, 0);
|
||||
|
||||
_Counter = initialCounter;
|
||||
|
||||
_CounterEncryptor = symmetricAlgorithm.CreateEncryptor(key, iv);
|
||||
|
||||
// Initialize State
|
||||
@ -204,7 +208,7 @@ namespace Teknik.Utilities.Cryptography
|
||||
|
||||
public void ResetCounter()
|
||||
{
|
||||
_IV.CopyTo(_Counter);
|
||||
_IV.CopyTo(_Counter, 0);
|
||||
_Iterations = 0;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ namespace Teknik.Utilities.Cryptography
|
||||
int processed = 0;
|
||||
|
||||
// Read the data from the stream
|
||||
int bytesRead = await _Inner.ReadAsync(buffer);
|
||||
int bytesRead = await _Inner.ReadAsync(buffer).ConfigureAwait(false);
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
// Process the read buffer
|
||||
@ -128,21 +128,20 @@ namespace Teknik.Utilities.Cryptography
|
||||
if (_Inner != null && CanWrite)
|
||||
{
|
||||
// Process the cipher
|
||||
Memory<byte> output = buffer;
|
||||
Span<byte> output = buffer;
|
||||
|
||||
// Process the buffer
|
||||
int processed = _Cipher.TransformBlock(output.Span, offset, count);
|
||||
int processed = _Cipher.TransformBlock(output, offset, count);
|
||||
|
||||
// Do we have more?
|
||||
if (processed < count)
|
||||
{
|
||||
// Finalize the cipher
|
||||
var finalProcessed = _Cipher.TransformFinalBlock(output.Span, processed + offset, count);
|
||||
var finalProcessed = _Cipher.TransformFinalBlock(output, processed + offset, count);
|
||||
if (finalProcessed > 0)
|
||||
processed += finalProcessed;
|
||||
}
|
||||
ReadOnlyMemory<byte> readOnlyOutput = buffer;
|
||||
_Inner.Write(readOnlyOutput.Span);
|
||||
_Inner.Write(output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,12 +254,6 @@ namespace Teknik.Utilities.Cryptography
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
await _Inner.DisposeAsync();
|
||||
await base.DisposeAsync();
|
||||
}
|
||||
|
||||
private void SyncCounter()
|
||||
{
|
||||
if (_Cipher != null)
|
||||
|
@ -11,8 +11,9 @@ namespace Teknik.Utilities
|
||||
{
|
||||
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;
|
||||
if (length < chunkSize)
|
||||
bufferSize = length;
|
||||
@ -27,11 +28,7 @@ namespace Teknik.Utilities
|
||||
{
|
||||
await response.Body.WriteAsync(buffer.Slice(0, processedBytes));
|
||||
|
||||
// Flush the response
|
||||
if (flush)
|
||||
{
|
||||
//await response.Body.FlushAsync();
|
||||
}
|
||||
await response.Body.FlushAsync();
|
||||
}
|
||||
}
|
||||
while (processedBytes > 0);
|
||||
@ -42,10 +39,10 @@ namespace Teknik.Utilities
|
||||
}
|
||||
finally
|
||||
{
|
||||
//await response.Body.FlushAsync();
|
||||
await response.Body.FlushAsync();
|
||||
|
||||
// dispose of file stream
|
||||
stream?.Dispose();
|
||||
//stream?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user