Skip to content

Instantly share code, notes, and snippets.

@TechnoDezi
Created October 3, 2016 19:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TechnoDezi/8858215e97157a2e4f453a89db1fe9e9 to your computer and use it in GitHub Desktop.
Save TechnoDezi/8858215e97157a2e4f453a89db1fe9e9 to your computer and use it in GitHub Desktop.
MVC Multiple File Upload
using MVCMultipleFileUpload.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MVCMultipleFileUpload.Helpers
{
public class FileUploadHelper
{
public UploadedFile GetFileFromRequest(HttpRequestBase Request)
{
string filename = null;
string fileType = null;
string fileData = null;
byte[] fileContents = null;
if (Request.Files.Count > 0)
{ //we are uploading the old way
var file = Request.Files[0];
fileContents = new byte[file.ContentLength];
file.InputStream.Read(fileContents, 0, file.ContentLength);
fileType = file.ContentType;
filename = file.FileName;
IDictionary<string, object> dict = new Dictionary<string, object>();
foreach (string key in Request.Form.Keys)
{
dict.Add(key, Request.Form.GetValues(key).FirstOrDefault());
}
dynamic dobj = dict.ToExpando();
fileData = Newtonsoft.Json.JsonConvert.SerializeObject(dobj);
}
else if (Request.ContentLength > 0)
{
// Using FileAPI the content is in Request.InputStream!!!!
fileContents = new byte[Request.ContentLength];
Request.InputStream.Read(fileContents, 0, Request.ContentLength);
filename = Request.Headers["X-File-Name"];
fileType = Request.Headers["X-File-Type"];
fileData = Request.Headers["X-File-Data"];
}
return new UploadedFile()
{
Filename = filename,
ContentType = fileType,
FileSize = fileContents != null ? fileContents.Length : 0,
Contents = fileContents,
FileData = fileData
};
}
}
}
function FileUploadViewModel(uploadUrl, dropBoxID, defaultFileImg, supportedExtentions, dataHeaderObj) {
var self = this;
self.uploadUrl = uploadUrl;
self.dropBoxID = dropBoxID;
self.defaultFileImg = defaultFileImg;
self.supportedExtentions = supportedExtentions;
self.dataHeaderObj = dataHeaderObj;
self.showResults = ko.observable(false);
self.showFileSelect = ko.observable(true);
self.showSubmit = ko.observable(true);
self.fileObj = function (fileName, fileSize, uploadPercentage, messages, showMessages) {
this.fileName = fileName;
this.fileSize = fileSize;
this.imgSrc = ko.observable("");
this.uploadPercentage = ko.observable(uploadPercentage);
this.messages = ko.observable(messages);
this.showMessages = ko.observable(showMessages);
}
self.fileList = ko.observableArray([]);
self.init = function () {
// Check if FileAPI and XmlHttpRequest.upload are supported, so that we can hide the old style input method
if (window.File && window.FileReader && window.FileList && window.Blob && new XMLHttpRequest().upload) {
self.showFileSelect(false);
self.showSubmit(false);
var dropbox = document.getElementById(self.dropBoxID);
// init event handlers
dropbox.addEventListener("dragenter", self.dragEnter, false);
dropbox.addEventListener("dragexit", self.dragExit, false);
dropbox.addEventListener("dragleave", self.dragExit, false);
dropbox.addEventListener("dragover", self.dragOver, false);
dropbox.addEventListener("drop", self.drop, false);
}
}
self.dragEnter = function (evt) {
evt.stopPropagation();
evt.preventDefault();
}
self.dragExit = function (evt) {
evt.stopPropagation();
evt.preventDefault();
$("#" + self.dropBoxID).removeClass("active-dropzone");
}
self.dragOver = function (evt) {
evt.stopPropagation();
evt.preventDefault();
$("#" + self.dropBoxID).addClass("active-dropzone");
}
self.drop = function (evt) {
evt.stopPropagation();
evt.preventDefault();
$("#" + self.dropBoxID).removeClass("active-dropzone");
var files = evt.dataTransfer.files;
var count = files.length;
self.fileList.removeAll();
// Only call the handler if a file was dropped
if (count > 0) {
self.showResults(true);
self.handleFiles(files);
}
else {
self.showResults(false);
}
}
self.handleFiles = function (files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var re = /(?:\.([^.]+))?$/;
var extention = re.exec(file.name)[1];
var fileName = file.name;
if (fileName.length > 100) {
fileName = fileName.substring(0, 100);
fileName = fileName + "...";
}
var size = file.size / 1024;
size = Math.round(size * Math.pow(10, 2)) / Math.pow(10, 2);
var fileModel = new self.fileObj(fileName, size + "Kb", "0%", "", false);
self.fileList.push(fileModel);
if ($.inArray(extention, self.supportedExtentions) > -1) {
self.HandleFilePreview(file, fileModel);
this.UploadFile(file, fileModel);
}
else {
var message = "File type not valid for file " + file.name + ".";
fileModel.messages(message);
fileModel.showMessages(true);
}
}
}
self.HandleFilePreview = function (file, fileModel) {
if (file.type.match('^image/')) {
var reader = new FileReader();
// init the reader event handlers
reader.onloadend = function (evt) {
fileModel.imgSrc(evt.target.result);
};
// begin the read operation
reader.readAsDataURL(file);
}
else {
fileModel.imgSrc(self.defaultFileImg);
}
}
self.UploadFile = function (file, fileModel) {
fileModel.uploadPercentage("0%");
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var percentageUploaded = parseInt(100 - (evt.loaded / evt.total * 100));
fileModel.uploadPercentage(percentageUploaded + "%");
}
}, false);
// File uploaded
xhr.addEventListener("load", function () {
fileModel.uploadPercentage("100%");
}, false);
// file received/failed
xhr.onreadystatechange = function (e) {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
console.log(xhr);
fileModel.messages(xhr.responseText);
fileModel.showMessages(true);
}
}
};
xhr.open("POST", self.uploadUrl, true);
// Set appropriate headers
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("X-File-Name", file.name);
xhr.setRequestHeader("X-File-Size", file.size);
xhr.setRequestHeader("X-File-Type", file.type);
if (self.dataHeaderObj != null && self.dataHeaderObj != "")
{
xhr.setRequestHeader("X-File-Data", self.dataHeaderObj);
}
// Send the file
xhr.send(file);
}
//Load View Model
self.init();
}
[HttpPost]
public async Task<string> UploadFilePost()
{
FileUploadHelper handler = new FileUploadHelper();
//Retriev the file from the request
UploadedFile fileObj = handler.GetFileFromRequest(this.Request);
//Write file to disc
System.IO.File.WriteAllBytes(Path.Combine(Server.MapPath("~/App_Data/"), Guid.NewGuid() + Path.GetExtension(fileObj.Filename)), fileObj.Contents);
return "File uploaded";
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MVCMultipleFileUpload.Models
{
public class UploadedFile
{
public int FileSize { get; set; }
public string Filename { get; set; }
public string ContentType { get; set; }
public byte[] Contents { get; set; }
public string FileData { get; set; }
}
}
@{
ViewBag.Title = "Upload File";
}
@section scripts
{
<script src="~/Scripts/knockout-3.4.0.js"></script>
<script src="~/Scripts/FileUploadViewModel.js"></script>
<script type="text/javascript">
$(function () {
//var data = @(Html.Raw(Json.Encode(this.Model)));
//var jsonModel = JSON.stringify(data);
var jsonModel = null;
ko.applyBindings(new FileUploadViewModel(
"@Url.Action("UploadFilePost", "Home")",
"dropbox",
"@Url.Content("~/Content/images/file_type_icons_flat_-13.png")",
["jpg", "png"],
jsonModel), document.getElementById("fileUploadContainer"));
});
</script>
}
<div id="fileUploadContainer">
@using (Html.BeginForm("UploadFilePost", "Home", FormMethod.Post, new { @class = "form-horizontal", role = "form", enctype = "multipart/form-data" }))
{
<br />
<div id="dropbox" dropzone="copy f:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet f:application/vnd.ms-excel" class="hero-unit">
<h2 id="droplabel">Drop zone - Drag & Drop your files here</h2>
<p id="dnd-notes">Only jpg and png file types are supported. Once you drop your files in the dropzone, the upload will start.</p>
<input data-bind="visible: showFileSelect" id="fileSelect" type="file" name="fileSelect" />
<p><button data-bind="visible: showSubmit" type="submit" class="btn btn-primary btn-large">Upload</button></p>
</div>
<table class="table table-striped" data-bind="visible: showResults">
<thead>
<tr>
<th></th>
<th>File name</th>
<th>File size</th>
<th>Upload Progress</th>
<th>Message</th>
</tr>
</thead>
<tbody data-bind="foreach: fileList">
<tr>
<td>
<img style="max-height: 80px" data-bind="attr: { src: imgSrc }" alt="preview will display here" />
</td>
<td data-bind="text: fileName"></td>
<td data-bind="text: fileSize"></td>
<td>
<div class="progress progress-info progress-striped">
<div class="progress-bar" data-bind="style: { width: uploadPercentage }"></div>
</div>
</td>
<td>
<div data-bind="visible: showMessages, html: messages">
</div>
</td>
</tr>
</tbody>
</table>
}
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment