Browse Source

Small mods to download function

tags/3.0.0
Teknikode 2 years ago
parent
commit
19b6564ccd

+ 95
- 82
Teknik/Areas/Upload/Controllers/UploadController.cs View File

@@ -126,104 +126,117 @@ namespace Teknik.Areas.Upload.Controllers
if (Config.UploadConfig.DownloadEnabled)
{
ViewBag.Title = "Teknik Download - " + file;
string fileName = string.Empty;
string url = string.Empty;
string key = string.Empty;
string iv = string.Empty;
string contentType = string.Empty;
long contentLength = 0;
DateTime dateUploaded = new DateTime();

using (TeknikEntities db = new TeknikEntities())
{
Models.Upload upload = db.Uploads.Where(up => up.Url == file).FirstOrDefault();
if (upload != null)
Models.Upload uploads = db.Uploads.Where(up => up.Url == file).FirstOrDefault();
if (uploads != null)
{
upload.Downloads += 1;
db.Entry(upload).State = EntityState.Modified;
uploads.Downloads += 1;
db.Entry(uploads).State = EntityState.Modified;
db.SaveChanges();

// We don't have the key, so we need to decrypt it client side
if (string.IsNullOrEmpty(upload.Key) && !string.IsNullOrEmpty(upload.IV))
{
DownloadViewModel model = new DownloadViewModel();
model.FileName = file;
model.ContentType = upload.ContentType;
model.ContentLength = upload.ContentLength;
model.IV = upload.IV;
fileName = uploads.FileName;
url = uploads.Url;
key = uploads.Key;
iv = uploads.IV;
contentType = uploads.ContentType;
contentLength = uploads.ContentLength;
dateUploaded = uploads.DateUploaded;
}
}

return View(model);
}
else // We have the key, so that means server side decryption
{
// Are they downloading it by range?
bool byRange = !string.IsNullOrEmpty(Request.ServerVariables["HTTP_RANGE"]); // We do not support ranges
// Check to see if they have a cache
bool isCached = !string.IsNullOrEmpty(Request.Headers["If-Modified-Since"]);
// We don't have the key, so we need to decrypt it client side
if (string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(iv))
{
DownloadViewModel model = new DownloadViewModel();
model.FileName = file;
model.ContentType = contentType;
model.ContentLength = contentLength;
model.IV = iv;

if (isCached)
{
// The file is cached, let's just 304 this
Response.StatusCode = 304;
Response.StatusDescription = "Not Modified";
Response.AddHeader("Content-Length", "0");
return Content(string.Empty);
}
else
{
string subDir = upload.FileName[0].ToString();
string filePath = Path.Combine(Config.UploadConfig.UploadDirectory, subDir, upload.FileName);
if (System.IO.File.Exists(filePath))
{
// Add cache parameters
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetMaxAge(new TimeSpan(365, 0, 0, 0));
Response.Cache.SetLastModified(upload.DateUploaded);
return View(model);
}
else // We have the key, so that means server side decryption
{
// Are they downloading it by range?
bool byRange = !string.IsNullOrEmpty(Request.ServerVariables["HTTP_RANGE"]); // We do not support ranges
// Check to see if they have a cache
bool isCached = !string.IsNullOrEmpty(Request.Headers["If-Modified-Since"]);

if (isCached)
{
// The file is cached, let's just 304 this
Response.StatusCode = 304;
Response.StatusDescription = "Not Modified";
Response.AddHeader("Content-Length", "0");
return Content(string.Empty);
}
else
{
string subDir = fileName[0].ToString();
string filePath = Path.Combine(Config.UploadConfig.UploadDirectory, subDir, fileName);
if (System.IO.File.Exists(filePath))
{
// Add cache parameters
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetMaxAge(new TimeSpan(365, 0, 0, 0));
Response.Cache.SetLastModified(dateUploaded);

// Notify the client the content length we'll be outputting
Response.AddHeader("Content-Length", upload.ContentLength.ToString());
// Notify the client the content length we'll be outputting
Response.AddHeader("Content-Length", contentLength.ToString());

// Create content disposition
var cd = new System.Net.Mime.ContentDisposition
{
FileName = upload.Url,
Inline = true
};
// Create content disposition
var cd = new System.Net.Mime.ContentDisposition
{
FileName = url,
Inline = true
};

Response.AddHeader("Content-Disposition", cd.ToString());
Response.AddHeader("Content-Disposition", cd.ToString());

string contentType = upload.ContentType;
// We need to prevent html (make cleaner later)
if (contentType == "text/html")
{
contentType = "text/plain";
}
// We need to prevent html (make cleaner later)
if (contentType == "text/html")
{
contentType = "text/plain";
}

// Read in the file
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
// Read in the file
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);

try
{
// If the IV is set, and Key is set, then decrypt it while sending
if (!string.IsNullOrEmpty(upload.Key) && !string.IsNullOrEmpty(upload.IV))
{
byte[] keyBytes = Encoding.UTF8.GetBytes(upload.Key);
byte[] ivBytes = Encoding.UTF8.GetBytes(upload.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);

return new FileGenerateResult(upload.Url,
contentType,
(response) => ResponseHelper.StreamToOutput(response, true, new AESCryptoStream(fs, false, keyBytes, ivBytes, "CTR", "NoPadding"), (int)upload.ContentLength, Config.UploadConfig.ChunkSize),
false);
}
else // Otherwise just send it
{
// Don't buffer the response
Response.Buffer = false;
// Send the file
return new FileGenerateResult(upload.Url,
contentType,
(response) => ResponseHelper.StreamToOutput(response, true, fs, (int)upload.ContentLength, Config.UploadConfig.ChunkSize),
false);
}
}
catch (Exception ex)
{
Logging.Logger.WriteEntry(Logging.LogLevel.Warning, "Error in Download", ex);
}
return new FileGenerateResult(url,
contentType,
(response) => ResponseHelper.StreamToOutput(response, true, new AESCryptoStream(fs, false, keyBytes, ivBytes, "CTR", "NoPadding"), (int)contentLength, Config.UploadConfig.ChunkSize),
false);
}
else // Otherwise just send it
{
// Send the file
return new FileGenerateResult(url,
contentType,
(response) => ResponseHelper.StreamToOutput(response, true, fs, (int)contentLength, Config.UploadConfig.ChunkSize),
false);
}
}
catch (Exception ex)
{
Logging.Logger.WriteEntry(Logging.LogLevel.Warning, "Error in Download", ex);
}
}
}
return Redirect(Url.SubRouteUrl("error", "Error.Http404"));

+ 23
- 9
Utilities/Utilities/ResponseHelper.cs View File

@@ -17,6 +17,11 @@ namespace Teknik.Utilities
{
if (flush)
{
// If the client isn't here, just quit early
if (!response.IsClientConnected)
{
return;
}
response.Flush();
}

@@ -31,29 +36,38 @@ namespace Teknik.Utilities
{
bytesToRead = bytesRemaining;
}
processedBytes = stream.Read(buffer, 0, bytesToRead);
if (processedBytes > 0)
{
response.OutputStream.Write(buffer, 0, processedBytes);
if (flush)
// If the client isn't here, just quit early
if (!response.IsClientConnected)
{
response.Flush();
return;
}

response.OutputStream.Write(buffer, 0, processedBytes);

// Clear the buffer
Array.Clear(buffer, 0, chunkSize);

// Flush the response
if (flush)
{
// If the client isn't here, just quit early
if (!response.IsClientConnected)
{
return;
}
//response.OutputStream.Write(buffer, 0, 1);
response.Flush();
}
}
curByte += processedBytes;
bytesRemaining -= processedBytes;
}
while (processedBytes > 0 && bytesRemaining > 0);
}
catch (Exception ex)
{
// Don't bother
throw ex;
}
finally
{
// dispose of file stream

Loading…
Cancel
Save