mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Implemented file download and decryption. Still need to re-create file from ArrayBuffer.
This commit is contained in:
parent
5396a4ddee
commit
252d605ce0
@ -1,16 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Teknik.Areas.Upload.Models;
|
||||
using Teknik.Areas.Upload.ViewModels;
|
||||
using Teknik.Controllers;
|
||||
using Teknik.Models;
|
||||
|
||||
namespace Teknik.Areas.Upload.Controllers
|
||||
{
|
||||
public class UploadController : DefaultController
|
||||
{
|
||||
private TeknikEntities db = new TeknikEntities();
|
||||
|
||||
// GET: Upload/Upload
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
@ -19,33 +23,90 @@ namespace Teknik.Areas.Upload.Controllers
|
||||
return View(new UploadViewModel());
|
||||
}
|
||||
|
||||
// User did not supply key
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public ActionResult Download(string url)
|
||||
{
|
||||
return View(new UploadViewModel());
|
||||
}
|
||||
|
||||
// User supplied key
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public ActionResult Download(string url, string key)
|
||||
{
|
||||
return View(new UploadViewModel());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public ActionResult Upload(string fileType, string iv, HttpPostedFileWrapper data)
|
||||
{
|
||||
Models.Upload upload = Uploader.SaveFile(data, fileType, iv);
|
||||
if (data.ContentLength <= Config.UploadConfig.MaxUploadSize)
|
||||
{
|
||||
Models.Upload upload = Uploader.SaveFile(data, fileType, iv);
|
||||
if (upload != null)
|
||||
{
|
||||
return Json(new { result = new { name = upload.Url, url = Url.SubRouteUrl("upload", "Upload.Download", new { file = upload.Url }) } }, "text/plain");
|
||||
}
|
||||
return Json(new { error = "Unable to upload file" });
|
||||
}
|
||||
else
|
||||
{
|
||||
return Json(new { error = "File Too Large" });
|
||||
}
|
||||
}
|
||||
|
||||
// User did not supply key
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public ActionResult Download(string file)
|
||||
{
|
||||
Models.Upload upload = db.Uploads.Where(up => up.Url == file).FirstOrDefault();
|
||||
if (upload != null)
|
||||
{
|
||||
return Json(new { result = new { name = upload.Url, url = Url.SubRouteUrl("upload", "Upload.Download.Key", new { file = upload.Url, key = "{key}" }), keyVar = "{key}" } }, "text/plain");
|
||||
// We don't have the key, so we need to decrypt it client side
|
||||
if (upload.Key == null)
|
||||
{
|
||||
DownloadViewModel model = new DownloadViewModel();
|
||||
model.FileName = file;
|
||||
model.ContentType = upload.ContentType;
|
||||
model.Key = upload.Key;
|
||||
model.IV = upload.IV;
|
||||
|
||||
return View(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
// decrypt it server side! Weee
|
||||
return View();
|
||||
}
|
||||
}
|
||||
return Json(new { error = "Unable to upload file" });
|
||||
else
|
||||
{
|
||||
return RedirectToRoute("Error.Http404");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public FileResult DownloadData(string file)
|
||||
{
|
||||
Models.Upload upload = db.Uploads.Where(up => up.Url == file).FirstOrDefault();
|
||||
if (upload != null)
|
||||
{
|
||||
string filePath = Path.Combine(Config.UploadConfig.UploadDirectory, upload.FileName);
|
||||
if (System.IO.File.Exists(filePath))
|
||||
{
|
||||
byte[] buffer;
|
||||
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
||||
try
|
||||
{
|
||||
int length = (int)fileStream.Length; // get file length
|
||||
buffer = new byte[length]; // create buffer
|
||||
int count; // actual number of bytes read
|
||||
int sum = 0; // total number of bytes read
|
||||
|
||||
// read until Read method returns 0 (end of the stream has been reached)
|
||||
while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
|
||||
sum += count; // sum is a buffer offset for next reading
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileStream.Close();
|
||||
}
|
||||
return File(buffer, System.Net.Mime.MediaTypeNames.Application.Octet, file);
|
||||
}
|
||||
}
|
||||
RedirectToAction("Http404", "Error", new { area = "Errors", exception = new Exception("File Not Found") });
|
||||
return null;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
|
55
Teknik/Areas/Upload/Scripts/Download.js
Normal file
55
Teknik/Areas/Upload/Scripts/Download.js
Normal file
@ -0,0 +1,55 @@
|
||||
$(document).ready(downloadFile);
|
||||
|
||||
function downloadFile() {
|
||||
var fd = new FormData();
|
||||
fd.append('file', fileName);
|
||||
fd.append('__RequestVerificationToken', $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val());
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', downloadDataUrl, true);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
|
||||
xhr.onload = function (e) {
|
||||
if (this.status == 200) {
|
||||
var worker = new Worker(encScriptSrc);
|
||||
|
||||
worker.addEventListener('message', function (e) {
|
||||
switch (e.data.cmd) {
|
||||
case 'progress':
|
||||
var percentComplete = Math.round(e.data.processed * 100 / e.data.total);
|
||||
$("#progress").children('.progress-bar').css('width', (percentComplete * (2 / 5)) + 20 + '%');
|
||||
$("#progress").children('.progress-bar').html(percentComplete + '% Decrypted');
|
||||
break;
|
||||
case 'finish':
|
||||
var blob = new Blob([e.data.buffer], { type: fileType });
|
||||
var url = (window.webkitURL || window.URL).createObjectURL(blob);
|
||||
location.href = url; // <-- Download!
|
||||
// DO SOMETHING
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
worker.onerror = function (err) {
|
||||
// An error occured
|
||||
$("#progress").children('.progress-bar').css('width', '100%');
|
||||
$("#progress").children('.progress-bar').removeClass('progress-bar-success');
|
||||
$("#progress").children('.progress-bar').addClass('progress-bar-danger');
|
||||
$("#progress").children('.progress-bar').html('Error Occured');
|
||||
}
|
||||
|
||||
// Execute worker with data
|
||||
var objData =
|
||||
{
|
||||
cmd: 'decrypt',
|
||||
script: aesScriptSrc,
|
||||
key: key,
|
||||
iv: iv,
|
||||
chunkSize: chunkSize,
|
||||
file: this.response
|
||||
};
|
||||
worker.postMessage(objData, [objData.file]);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(fd);
|
||||
}
|
@ -1,88 +1,85 @@
|
||||
self.addEventListener('message', function (e) {
|
||||
importScripts(e.data.script);
|
||||
var bytes = new Uint8Array(e.data.file);
|
||||
|
||||
var startByte = 0;
|
||||
var endByte = 0;
|
||||
var prog = [];
|
||||
|
||||
var key = CryptoJS.enc.Utf8.parse(e.data.key);
|
||||
var iv = CryptoJS.enc.Utf8.parse(e.data.iv);
|
||||
|
||||
// Create aes encryptor object
|
||||
var aesCrypto;
|
||||
switch (e.data.cmd) {
|
||||
case 'encrypt':
|
||||
var bytes = new Uint8Array(e.data.file);
|
||||
|
||||
var startByte = 0;
|
||||
var endByte = 0;
|
||||
var prog = [];
|
||||
|
||||
var key = CryptoJS.enc.Utf8.parse(e.data.key);
|
||||
var iv = CryptoJS.enc.Utf8.parse(e.data.iv);
|
||||
// Create aes encryptor object
|
||||
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
|
||||
|
||||
while (startByte <= (bytes.length - 1)) {
|
||||
// Set the end byte
|
||||
endByte = startByte + e.data.chunkSize;
|
||||
if (endByte > bytes.length - 1)
|
||||
{
|
||||
endByte = bytes.length - 1;
|
||||
}
|
||||
|
||||
// Grab current set of bytes
|
||||
var curBytes = bytes.subarray(startByte, endByte);
|
||||
//var b64encoded = btoa(String.fromCharCode.apply(null, curBytes));
|
||||
var wordArray = CryptoJS.lib.WordArray.create(curBytes)
|
||||
|
||||
// encrypt the passed in file data
|
||||
var enc = aesEncryptor.process(wordArray);
|
||||
|
||||
// Convert and add to current array buffer
|
||||
var encStr = enc.toString(CryptoJS.enc.Base64); // to string
|
||||
prog.pushArray(_base64ToArray(encStr));
|
||||
|
||||
// Send an update on progress
|
||||
var objData =
|
||||
{
|
||||
cmd: 'progress',
|
||||
processed: endByte,
|
||||
total: bytes.length - 1
|
||||
};
|
||||
|
||||
self.postMessage(objData);
|
||||
|
||||
// Set the next start as the current end
|
||||
startByte = endByte + 1;
|
||||
}
|
||||
|
||||
//then finalize
|
||||
var encFinal = aesEncryptor.finalize();
|
||||
var finalStr = encFinal.toString(CryptoJS.enc.Base64); // to final string
|
||||
prog.pushArray(_base64ToArray(finalStr));
|
||||
|
||||
var objData =
|
||||
{
|
||||
cmd: 'progress',
|
||||
processed: bytes.length - 1,
|
||||
total: bytes.length - 1
|
||||
};
|
||||
|
||||
// convert array to ArrayBuffer
|
||||
var arBuf = _arrayToArrayBuffer(prog);
|
||||
|
||||
//throw JSON.stringify({ dataLength: prog.length, len: bytes.length, finalLength: arBuf.byteLength })
|
||||
|
||||
// Now package it into a mesage to send home
|
||||
var objData =
|
||||
{
|
||||
cmd: 'finish',
|
||||
encrypted: arBuf
|
||||
};
|
||||
|
||||
self.postMessage(objData, [objData.encrypted]);
|
||||
aesCrypto = CryptoJS.algo.AES.createEncryptor(key, { iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
|
||||
break;
|
||||
case 'decrypt':
|
||||
// decrypt the passed in file data
|
||||
var decrypted = CryptoJS.AES.decrypt(e.data.file, e.data.key, { iv: e.data.iv });
|
||||
|
||||
var fileText = decrypted.toString();
|
||||
|
||||
self.postMessage(fileText);
|
||||
aesCrypto = CryptoJS.algo.AES.createDecryptor(key, { iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while (startByte <= (bytes.length - 1)) {
|
||||
// Set the end byte
|
||||
endByte = startByte + e.data.chunkSize;
|
||||
if (endByte > bytes.length - 1) {
|
||||
endByte = bytes.length - 1;
|
||||
}
|
||||
|
||||
// Grab current set of bytes
|
||||
var curBytes = bytes.subarray(startByte, endByte);
|
||||
//var b64encoded = btoa(String.fromCharCode.apply(null, curBytes));
|
||||
var wordArray = CryptoJS.lib.WordArray.create(curBytes)
|
||||
|
||||
// encrypt the passed in file data
|
||||
var enc = aesCrypto.process(wordArray);
|
||||
|
||||
// Convert and add to current array buffer
|
||||
var encStr = enc.toString(CryptoJS.enc.Base64); // to string
|
||||
prog.pushArray(_base64ToArray(encStr));
|
||||
|
||||
// Send an update on progress
|
||||
var objData =
|
||||
{
|
||||
cmd: 'progress',
|
||||
processed: endByte,
|
||||
total: bytes.length - 1
|
||||
};
|
||||
|
||||
self.postMessage(objData);
|
||||
|
||||
// Set the next start as the current end
|
||||
startByte = endByte + 1;
|
||||
}
|
||||
|
||||
//then finalize
|
||||
var encFinal = aesCrypto.finalize();
|
||||
var finalStr = encFinal.toString(CryptoJS.enc.Base64); // to final string
|
||||
prog.pushArray(_base64ToArray(finalStr));
|
||||
|
||||
var objData =
|
||||
{
|
||||
cmd: 'progress',
|
||||
processed: bytes.length - 1,
|
||||
total: bytes.length - 1
|
||||
};
|
||||
|
||||
// convert array to ArrayBuffer
|
||||
var arBuf = _arrayToArrayBuffer(prog);
|
||||
|
||||
//throw JSON.stringify({ dataLength: prog.length, len: bytes.length, finalLength: arBuf.byteLength })
|
||||
|
||||
// Now package it into a mesage to send home
|
||||
var objData =
|
||||
{
|
||||
cmd: 'finish',
|
||||
buffer: arBuf
|
||||
};
|
||||
|
||||
self.postMessage(objData, [objData.buffer]);
|
||||
}, false);
|
||||
|
||||
function _arrayToArrayBuffer(array) {
|
||||
|
@ -53,6 +53,13 @@ function linkRemove(selector, fileID) {
|
||||
});
|
||||
}
|
||||
|
||||
function linkCancel(selector, fileID) {
|
||||
$(selector).click(function () {
|
||||
$('#link-' + fileID).remove();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
var fileCount = 0;
|
||||
|
||||
var dropZone = new Dropzone(document.body, {
|
||||
@ -84,11 +91,31 @@ var dropZone = new Dropzone(document.body, {
|
||||
</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
<div class="panel-footer" id="link-footer-' + fileID + '"> \
|
||||
<div class="row"> \
|
||||
<div class="col-sm-12 text-center"> \
|
||||
<button type="button" class="btn btn-default btn-sm" id="remove-link-' + fileID + '">Remove From List</button> \
|
||||
</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
');
|
||||
|
||||
// Encrypt the file
|
||||
encryptFile(file, uploadFile);
|
||||
linkRemove('#remove-link-' + fileID + '', fileID);
|
||||
|
||||
// Check the file size
|
||||
if (file.size <= maxUploadSize) {
|
||||
// Encrypt the file and upload it
|
||||
encryptFile(file, uploadFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// An error occured
|
||||
$("#progress-" + fileID).children('.progress-bar').css('width', '100%');
|
||||
$("#progress-" + fileID).children('.progress-bar').removeClass('progress-bar-success');
|
||||
$("#progress-" + fileID).children('.progress-bar').addClass('progress-bar-danger');
|
||||
$("#progress-" + fileID).children('.progress-bar').html('File Too Large');
|
||||
}
|
||||
this.removeFile(file);
|
||||
}
|
||||
});
|
||||
@ -108,6 +135,13 @@ function encryptFile(file, callback) {
|
||||
var keyStr = randomString(24, '#aA');
|
||||
var ivStr = randomString(24, '#aA');
|
||||
|
||||
// Let's grab the header and get the file type
|
||||
var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
|
||||
var header = "";
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
header += arr[i].toString(16);
|
||||
}
|
||||
|
||||
var worker = new Worker(encScriptSrc);
|
||||
|
||||
worker.addEventListener('message', function (e) {
|
||||
@ -121,7 +155,7 @@ function encryptFile(file, callback) {
|
||||
case 'finish':
|
||||
if (callback != null) {
|
||||
// Finish
|
||||
callback(e.data.encrypted, keyStr, ivStr, filetype, fileID);
|
||||
callback(e.data.buffer, keyStr, ivStr, filetype, fileID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -194,13 +228,10 @@ function uploadComplete(fileID, key, evt) {
|
||||
obj = JSON.parse(evt.target.responseText);
|
||||
var name = obj.result.name;
|
||||
var fullName = decodeURIComponent(obj.result.url);
|
||||
var keyVar = decodeURIComponent(obj.result.keyVar);
|
||||
fullName = fullName.replace(keyVar, key);
|
||||
$('#progress-' + fileID).children('.progress-bar').css('width', '100%');
|
||||
$('#progress-' + fileID).children('.progress-bar').html('Complete');
|
||||
$('#upload-link-' + fileID).html('<p><a href="' + fullName + '" target="_blank" class="alert-link">' + fullName + '</a></p>');
|
||||
$('#link-' + fileID).append(' \
|
||||
<div class="panel-footer"> \
|
||||
$('#upload-link-' + fileID).html('<p><a href="' + fullName + '#' + key + '" target="_blank" class="alert-link">' + fullName + '#' + key + '</a></p>');
|
||||
$('#link-footer-' + fileID).html(' \
|
||||
<div class="row"> \
|
||||
<div class="col-sm-4 text-center"> \
|
||||
<button type="button" class="btn btn-default btn-sm" id="save-key-link-' + fileID + '">Save Key On Server</button> \
|
||||
@ -212,7 +243,6 @@ function uploadComplete(fileID, key, evt) {
|
||||
<button type="button" class="btn btn-default btn-sm" id="remove-link-' + fileID + '">Remove From List</button> \
|
||||
</div> \
|
||||
</div> \
|
||||
</div> \
|
||||
');
|
||||
linkSaveKey('#save-key-link-' + fileID + '', name, key, fileID);
|
||||
linkUploadDelete('#generate-delete-link-' + fileID + '', name);
|
||||
@ -232,3 +262,25 @@ function uploadCanceled(fileID, evt) {
|
||||
$("#progress-" + fileID).children('.progress-bar').addClass('progress-bar-warning');
|
||||
$('#progress-' + fileID).children('.progress-bar').html('Upload Canceled');
|
||||
}
|
||||
|
||||
function GetMIMEType(header)
|
||||
{
|
||||
var type = "";
|
||||
switch (header) {
|
||||
case "89504e47":
|
||||
type = "image/png";
|
||||
break;
|
||||
case "47494638":
|
||||
type = "image/gif";
|
||||
break;
|
||||
case "ffd8ffe0":
|
||||
case "ffd8ffe1":
|
||||
case "ffd8ffe2":
|
||||
type = "image/jpeg";
|
||||
break;
|
||||
default:
|
||||
type = "unknown"; // Or you can use the blob.type as fallback
|
||||
break;
|
||||
}
|
||||
return type;
|
||||
}
|
@ -29,13 +29,6 @@ namespace Teknik.Areas.Upload
|
||||
new { controller = "Upload", action = "Download", url = string.Empty },
|
||||
new[] { typeof(Controllers.UploadController).Namespace }
|
||||
);
|
||||
context.MapSubdomainRoute(
|
||||
"Upload.Download.Key",
|
||||
"dev",
|
||||
"Upload/{file}/{key}",
|
||||
new { controller = "Upload", action = "Download", url = string.Empty },
|
||||
new[] { typeof(Controllers.UploadController).Namespace }
|
||||
);
|
||||
context.MapSubdomainRoute(
|
||||
"Upload.Delete",
|
||||
"dev",
|
||||
@ -111,8 +104,9 @@ namespace Teknik.Areas.Upload
|
||||
BundleTable.Bundles.Add(new ScriptBundle("~/bundles/upload").Include(
|
||||
"~/Scripts/Dropzone/dropzone.js",
|
||||
"~/Areas/Upload/Scripts/Upload.js",
|
||||
"~/Scripts/bootbox/bootbox.min.js",
|
||||
"~/Scripts/Crypto-js/aes.js"));
|
||||
"~/Scripts/bootbox/bootbox.min.js"));
|
||||
BundleTable.Bundles.Add(new ScriptBundle("~/bundles/download").Include(
|
||||
"~/Areas/Upload/Scripts/Download.js"));
|
||||
BundleTable.Bundles.Add(new ScriptBundle("~/bundles/cryptoWorker").Include(
|
||||
"~/Areas/Upload/Scripts/EncryptionWorker.js"));
|
||||
BundleTable.Bundles.Add(new ScriptBundle("~/bundles/crypto").Include(
|
||||
|
@ -50,6 +50,7 @@ namespace Teknik.Areas.Upload
|
||||
upload.IV = iv;
|
||||
|
||||
db.Uploads.Add(upload);
|
||||
db.SaveChanges();
|
||||
|
||||
return upload;
|
||||
}
|
||||
|
16
Teknik/Areas/Upload/ViewModels/DownloadViewModel.cs
Normal file
16
Teknik/Areas/Upload/ViewModels/DownloadViewModel.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Upload.ViewModels
|
||||
{
|
||||
public class DownloadViewModel : ViewModelBase
|
||||
{
|
||||
public string FileName { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
public string Key { get; set; }
|
||||
public string IV { get; set; }
|
||||
}
|
||||
}
|
@ -1 +1,29 @@
|
||||
@model Teknik.Areas.Upload.ViewModels.UploadViewModel
|
||||
@model Teknik.Areas.Upload.ViewModels.DownloadViewModel
|
||||
|
||||
<script>
|
||||
var encScriptSrc = '@Scripts.Url("~/bundles/cryptoWorker")';
|
||||
var aesScriptSrc = '@Scripts.Url("~/bundles/crypto")';
|
||||
var downloadDataUrl = '@Url.SubRouteUrl("upload", "Upload.Action", new { action = "DownloadData" })';
|
||||
var fileName = '@Model.FileName';
|
||||
var fileType = '@Model.ContentType';
|
||||
var key = window.location.hash.substring(1);
|
||||
if (key == null)
|
||||
{
|
||||
key = '@((Model.Key != null) ? Model.Key : string.Empty)';
|
||||
}
|
||||
var iv = '@Model.IV';
|
||||
var chunkSize = @(Model.Config.UploadConfig.ChunkSize);
|
||||
</script>
|
||||
|
||||
<!-- Add UI for downloading info -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="progress" id="progress">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 0%">0%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@Scripts.Render("~/bundles/download")
|
@ -6,8 +6,8 @@
|
||||
var generateDeleteKeyURL = '@Url.SubRouteUrl("upload", "Upload.Action", new { action= "GenerateDeleteKey" })';
|
||||
var saveKeyToServerURL = '@Url.SubRouteUrl("upload", "Upload.Action", new { action= "SaveFileKey" })';
|
||||
var uploadFileURL = '@Url.SubRouteUrl("upload", "Upload.Action", new { action = "Upload" })';
|
||||
var maxUploadSize = @(Model.Config.UploadConfig.MaxUploadSize / 100000);
|
||||
var chunkSize = @(Model.Config.UploadConfig.ChunkSize);
|
||||
var maxUploadSize = @Model.Config.UploadConfig.MaxUploadSize;
|
||||
var chunkSize = @Model.Config.UploadConfig.ChunkSize;
|
||||
</script>
|
||||
|
||||
@Styles.Render("~/Content/upload")
|
||||
@ -47,7 +47,14 @@
|
||||
<div class="container" id="upload-links">
|
||||
</div>
|
||||
<br />
|
||||
<div class="well text-center">Each file is encrypted on upload using an AES-256-CTR cipher. If you wish to view the file decrypted, you must use the direct Teknik link.</div>
|
||||
<div class="well text-center">
|
||||
<p>
|
||||
Each file is encrypted on upload using an AES-256-CTR cipher. If you wish to view the file decrypted, you must use the direct Teknik link.
|
||||
</p>
|
||||
<p>
|
||||
The maximum file size per upload is <b>@Utility.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSize)</b>
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
Useful Tools: <a href="http://git.teknik.io/Teknikode/Tools/src/master/Upload">Upload Scripts and Utilities</a> | <a href="https://github.com/jschx/poomf">Poomf Uploader</a>
|
||||
<br />
|
||||
|
@ -88,5 +88,51 @@ namespace Teknik
|
||||
|
||||
return result;
|
||||
}
|
||||
public static string GetBytesReadable(long i)
|
||||
{
|
||||
// Get absolute value
|
||||
long absolute_i = (i < 0 ? -i : i);
|
||||
// Determine the suffix and readable value
|
||||
string suffix;
|
||||
double readable;
|
||||
if (absolute_i >= 0x1000000000000000) // Exabyte
|
||||
{
|
||||
suffix = "EB";
|
||||
readable = (i >> 50);
|
||||
}
|
||||
else if (absolute_i >= 0x4000000000000) // Petabyte
|
||||
{
|
||||
suffix = "PB";
|
||||
readable = (i >> 40);
|
||||
}
|
||||
else if (absolute_i >= 0x10000000000) // Terabyte
|
||||
{
|
||||
suffix = "TB";
|
||||
readable = (i >> 30);
|
||||
}
|
||||
else if (absolute_i >= 0x40000000) // Gigabyte
|
||||
{
|
||||
suffix = "GB";
|
||||
readable = (i >> 20);
|
||||
}
|
||||
else if (absolute_i >= 0x100000) // Megabyte
|
||||
{
|
||||
suffix = "MB";
|
||||
readable = (i >> 10);
|
||||
}
|
||||
else if (absolute_i >= 0x400) // Kilobyte
|
||||
{
|
||||
suffix = "KB";
|
||||
readable = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
return i.ToString("0 B"); // Byte
|
||||
}
|
||||
// Divide by 1024 to get fractional value
|
||||
readable = (readable / 1024);
|
||||
// Return formatted number with suffix
|
||||
return readable.ToString("0.### ") + suffix;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
@ -170,6 +170,7 @@
|
||||
<Compile Include="Areas\Upload\Models\Upload.cs" />
|
||||
<Compile Include="Areas\Upload\UploadAreaRegistration.cs" />
|
||||
<Compile Include="Areas\Upload\Uploader.cs" />
|
||||
<Compile Include="Areas\Upload\ViewModels\DownloadViewModel.cs" />
|
||||
<Compile Include="Areas\Upload\ViewModels\UploadViewModel.cs" />
|
||||
<Compile Include="Configuration\BlogConfig.cs" />
|
||||
<Compile Include="Configuration\Config.cs" />
|
||||
@ -209,6 +210,7 @@
|
||||
<Content Include="Areas\Home\Content\Home.css" />
|
||||
<Content Include="Areas\Home\Scripts\Home.js" />
|
||||
<Content Include="Areas\Profile\Scripts\Profile.js" />
|
||||
<Content Include="Areas\Upload\Scripts\Download.js" />
|
||||
<Content Include="Scripts\Crypto-js\aes.js" />
|
||||
<Content Include="Areas\Upload\Scripts\EncryptionWorker.js" />
|
||||
<Content Include="Areas\Upload\Scripts\Upload.js" />
|
||||
|
@ -27,7 +27,9 @@
|
||||
<modules>
|
||||
<remove name="FormsAuthentication" />
|
||||
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
|
||||
<add name="PerfModule" type="Teknik.Modules.PerformanceMonitorModule, Teknik" />
|
||||
<add name="PerfModule" type="Teknik.Modules.PerformanceMonitorModule, Teknik" />
|
||||
<remove name="UrlRoutingModule-4.0" />
|
||||
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
|
||||
</modules>
|
||||
<staticContent>
|
||||
<mimeMap fileExtension="woff" mimeType="application/font-woff" />
|
||||
|
Loading…
Reference in New Issue
Block a user