Folder Tree with Multiple File Upload with Progress Bar and Drag and Drop





5.00/5 (5 votes)
The ASP.NET pages let you upload, delete and browse files in a folder.
Introduction
This ASP.NET application will let you upload multiple files manually or via drag and drop. It will show progress bar for each file as it uploads. A zip file can be extracted after the upload. Once uploaded, you can browse and delete these files and folders.
Background
This is a sequel to my earlier article, Multiple file upload with progress bar and drag and drop. This version adds the following features:
- Ability to browse and expand folders
- Ability to zip and download all files
- Ability to upload and extract a zip file - this lets you create folders on the server
- Ability to search and sort files in the browser
This project uses:
- JQuery 1.12
- Bootstrap 3
- ICSharpCode.SharpZipLib.dll
- JavaScript Datatable control
To use this application:
- Download Upload3.zip and unzip it to C:\inetpub\wwwroot\Upload.
- Give everyone (or the IIS anonymous user) access to C:\inetpub\wwwroot\Upload\upload folderBr>
- In IIS Manager, right click Upload folder and convert it to Application.
- Point your browser to http://localhost/Upload/Upload.aspx?folder=upload.
- You can change URL from ?folder=upload to your folder like: folder=folder1 if you want to point the page to folder1.
Here is the code for Upload.js:
var iFiles = 0;
var iDoneFiles = 0;
var iFolderId = 0;
var oTable = null;
var bTableDirty = false;
function OnLoad() {
_("file1").addEventListener("change", FileSelectHandler, false);
var xhr = new XMLHttpRequest();
if (xhr.upload) {
var filedrag = _("divDropHere");
if (filedrag){
filedrag.addEventListener("dragover", FileDragHover, false);
filedrag.addEventListener("dragleave", FileDragHover, false);
filedrag.addEventListener("drop", FileSelectHandler, false);
filedrag.style.display = "block";
}
_("btnUpload").style.display = "none";
}
SetupDataTable();
SetupDeleteBtn();
}
function SetupDataTable() {
var h = $(window).height() - 310;
oTable = $('#tbServer').DataTable({
scrollY: h,
scrollCollapse: false,
paging: false,
searching: true,
ordering: true,
order: [],
"scrollX": true,
info: false
});
$('.dataTables_scrollHeadInner').mousedown(function (e) {
CleanDirtyTable()
});
$("input[type='search']").focus(function () {
CleanDirtyTable();
$("input[type='search']").focus();
})
}
function CleanDirtyTable() {
if (bTableDirty) {
ResetDataTable();
SetupDeleteBtn();
bTableDirty = false;
}
}
function Delete() {
if (confirm("Delete?")) {
form1.hdnAction.value = "Delete";
form1.submit();
}
}
function DownloadAll() {
if (confirm("Download all as one zip file?")) {
form1.hdnAction.value = "DownloadAll";
form1.submit();
}
}
function SetupDeleteBtn() {
$("input[name='chkDelete'],input[name='chkDeleteFolder'],input[name='chkDeleteAll']").click(function () {
$("#btnDelete").show("slow");
})
}
function FileDragHover(e) {
e.stopPropagation();
e.preventDefault();
e.target.className = (e.type=="dragover")?"hover":"";
}
function FileSelectHandler(e) {
FileDragHover(e);
var oFiles = e.target.files || e.dataTransfer.files;
if (oFiles.length == 0) return;
var sHtml = "";
for (var i = 0; i < oFiles.length; i++) {
var iSize = oFiles[i].size;
var sName = oFiles[i].name;
sHtml += "<tr><td>" + sName + "</td>"
+ "<td>" + (iSize / 1024).formatNumber(0, ',', '.') + " KB</td>"
+ "<td id=progressBar" + i + "></td></tr>";
}
if (sHtml != "") {
_("divStatus").innerHTML = "<table border=0 class='table table-striped'>" + sHtml + "</table>";
}
iFiles = oFiles.length;
for (var i = 0; i < oFiles.length; i++) {
UploadFile(oFiles[i], i);
}
}
function UploadFile(file, i) {
var xhr = new XMLHttpRequest();
if (xhr.upload) {
var progress = _("progressBar" + i).appendChild(document.createElement("div"));
progress.className = "progressBar";
progress.innerHTML = " ";
// progress bar
xhr.upload.addEventListener("progress", function (e) {
var pc = parseInt(100 - (e.loaded / e.total * 100));
progress.style.backgroundPosition = pc + "% 0";
}, false);
// file received/failed
xhr.onreadystatechange = function (e) {
if (xhr.readyState == 4) {
progress.className = "progressBar " + (xhr.status == 200 ? "progressSuccess" : "progressFailed");
if (xhr.status == 200) {
iDoneFiles += 1;
if (iFiles == iDoneFiles) {
//upload done: refresh
location = location.href;
return;
}
}
}
};
var oFormData = new FormData();
oFormData.append("myfile" + i, file);
oFormData.append("chkUnzip", form1.chkUnzip.checked ? "1": "");
xhr.open("POST", _("form1").action, true);
xhr.send(oFormData);
}
}
function DeleteAll(o){
var oBoxes = document.getElementsByTagName("input");
for (var i=1; i<oBoxes.length; i++){
oBoxes[i].checked = o.checked;
}
}
function _(id) {
return document.getElementById(id);
}
Number.prototype.formatNumber = function(decPlaces, thouSeparator, decSeparator) {
var n = this,
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
decSeparator = decSeparator == undefined ? "." : decSeparator,
thouSeparator = thouSeparator == undefined ? "," : thouSeparator,
sign = n < 0 ? "-" : "",
i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
j = (j = i.length) > 3 ? j % 3 : 0;
return sign + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};
function ExpandFolder(o) {
var tr = $(o).parent().parent();
var oImg = tr.find("img.Plus");
var id = tr.attr("data-folder-id");
if (id + "" != "undefined") {
if (oImg.attr("src").indexOf("plus.gif") != -1) {
oImg.attr("src", "images/minus.gif");
//expand files and folders
var oChildren = tr.parent().find("tr[data-parent-id='" + id + "']");
oChildren.show("fast");
} else {
oImg.attr("src", "images/plus.gif");
//collapse files, folders and subfolders
var oChildren = tr.parent().find("tr.p" + id);
oChildren.hide("fast");
oChildren.find("img.Plus").attr("src", "images/plus.gif");
}
return;
}
var sFolder = tr.attr("data-folder");
var iIndent = tr.attr("data-indent");
iIndent = parseInt(iIndent) + 1;
var sParentIds = tr.attr("data-parent-ids") || "";
iFolderId += 1;
tr.attr("data-folder-id", iFolderId);
oImg.attr("src", "images/minus.gif");
$.post("?subfolder=" + escape(sFolder) + "&indent=" + iIndent + "&folderId=" + iFolderId + "&parentIds=" + sParentIds, function (data) {
$(tr).after(data);
SetupDeleteBtn();
if (oTable) oTable.columns.adjust();
bTableDirty = true;
//ResetDataTable();
});
}
function ResetDataTable() {
$("#tbServer thead tr").remove();
var oHeadRow = $(".dataTables_scrollHeadInner").find("table thead tr").clone();
$("#tbServer thead").append(oHeadRow);
var oTbl = $("#tbServer").clone();
oTable.destroy();
$("#tbServer").remove();
$("#divTbl").append(oTbl)
SetupDataTable();
}
Here is the code for Upload.aspx.vb:
Public Class Upload
Inherits System.Web.UI.Page
Dim sFolder As String = "upload"
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Request.QueryString("folder") <> "" Then
sFolder = Request.QueryString("folder")
End If
Dim sFolderPath As String = Server.MapPath(sFolder)
If System.IO.Directory.Exists(sFolderPath) = False Then
Response.Write("Folder does not exist: " & sFolderPath)
Response.End()
End If
If Request.QueryString("subfolder") <> "" Then
GetSubFolder(Request.QueryString("subfolder"), Request.QueryString("indent"), Request.QueryString("folderId"), Request.QueryString("parentIds"))
Response.End()
End If
If Request.HttpMethod = "POST" Then
If Request.Form("hdnAction") = "Delete" Then
'Delete files
If (Not Request.Form.GetValues("chkDelete") Is Nothing) Then
For i As Integer = 0 To Request.Form.GetValues("chkDelete").Length - 1
Dim sFileName As String = Request.Form.GetValues("chkDelete")(i)
Try
System.IO.File.Delete(sFolderPath & "\" & sFileName)
Catch ex As Exception
'Ignore error
Throw New Exception("Could not delete: " & sFolderPath & "\" & sFileName)
End Try
Next
End If
'Delete Folders
If (Not Request.Form.GetValues("chkDeleteFolder") Is Nothing) Then
For i As Integer = 0 To Request.Form.GetValues("chkDeleteFolder").Length - 1
Dim sFolder As String = Request.Form.GetValues("chkDeleteFolder")(i)
Try
ClearFolder(sFolder)
System.IO.Directory.Delete(sFolder)
Catch ex As Exception
'Ignore error
End Try
Next
End If
ElseIf Request.Form("hdnAction") = "DownloadAll" Then
DownloadAll(sFolderPath)
Else
'Upload Files
For i As Integer = 0 To Request.Files.Count - 1
Dim oFile As System.Web.HttpPostedFile = Request.Files(i)
Dim sFileName As String = System.IO.Path.GetFileName(oFile.FileName)
If Request.Form("chkUnzip") <> "" AndAlso GetExtFromFileName(sFileName).ToLower() = "zip" Then
Dim sTempZipFilePath As String = sFolderPath & "\" & System.Guid.NewGuid().ToString("N") + ".zip"
oFile.SaveAs(sTempZipFilePath)
Dim oZip As New ICSharpCode.SharpZipLib.Zip.FastZip
oZip.ExtractZip(sTempZipFilePath, sFolderPath, Nothing)
System.IO.File.Delete(sTempZipFilePath)
Else
oFile.SaveAs(sFolderPath & "\" & sFileName)
End If
Next
End If
End If
End Sub
Private Sub DownloadAll(ByVal sFolderPath As String)
Dim oMemoryStream As New IO.MemoryStream()
Dim oZipFile As ICSharpCode.SharpZipLib.Zip.ZipOutputStream = New ICSharpCode.SharpZipLib.Zip.ZipOutputStream(oMemoryStream)
AddFilesToZip(oZipFile, sFolderPath, sFolderPath)
oZipFile.Finish()
Response.ContentType = "application/x-zip-compressed"
Response.AddHeader("Content-Disposition", "attachment; filename=All.zip")
Response.BinaryWrite(oMemoryStream.ToArray())
oMemoryStream.Close()
oZipFile.Close()
End Sub
Private oFilesInZip As New Hashtable
Private Sub AddFilesToZip(ByRef oZipFile As ICSharpCode.SharpZipLib.Zip.ZipOutputStream, ByVal sFolderName As String, ByVal sBaseFolderName As String)
Dim oFiles As String() = IO.Directory.GetFiles(sFolderName)
For Each sFileName As String In oFiles
Dim oFileInfo As New IO.FileInfo(sFileName)
Dim entryName As String = sFileName.Replace(sBaseFolderName, "")
AddFileToZip(oZipFile, sFileName, entryName)
Next
Dim oSubFolders As String() = IO.Directory.GetDirectories(sFolderName)
For Each sSubFolderName As String In oSubFolders
AddFilesToZip(oZipFile, sSubFolderName, sBaseFolderName)
Next
End Sub
Private Sub AddFileToZip(ByRef oZipFile As ICSharpCode.SharpZipLib.Zip.ZipOutputStream, ByVal sFileName As String, ByVal sEntryName As String)
sEntryName = ICSharpCode.SharpZipLib.Zip.ZipEntry.CleanName(sEntryName)
'Exit If file already in zip
If oFilesInZip.ContainsKey(sEntryName) Then
Exit Sub
Else
oFilesInZip.Add(sEntryName, "1")
End If
Dim fi As New IO.FileInfo(sFileName)
Dim newEntry As New ICSharpCode.SharpZipLib.Zip.ZipEntry(sEntryName)
newEntry.DateTime = fi.LastWriteTime
newEntry.Size = fi.Length
oZipFile.PutNextEntry(newEntry)
Dim buffer As Byte() = New Byte(4095) {}
Using streamReader As IO.FileStream = IO.File.OpenRead(sFileName)
ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(streamReader, oZipFile, buffer)
End Using
oZipFile.CloseEntry()
End Sub
Private Sub ClearFolder(ByVal FolderName As String)
Dim dir As System.IO.DirectoryInfo = New System.IO.DirectoryInfo(FolderName)
For Each fi As System.IO.FileInfo In dir.GetFiles()
fi.IsReadOnly = False
fi.Delete()
Next
For Each di As System.IO.DirectoryInfo In dir.GetDirectories()
ClearFolder(di.FullName)
di.Delete()
Next
End Sub
Private Sub GetSubFolder(ByVal sSubFolderPath As String, ByVal iIndent As Integer, ByVal sFolderId As String, ByVal sParentIds As String)
Dim sFolderIds As String = sFolderId
If sParentIds <> "" Then
sFolderIds = sParentIds & "," & sFolderId
End If
Dim sIndentCss As String = " style='padding-left:" & (iIndent * 15) & "px' "
Dim sUploadFolderPath As String = Server.MapPath(sFolder)
Dim sFolderPath As String = Server.MapPath(".")
Dim sSubFolderName As String = Replace(Replace(sSubFolderPath, sFolderPath & "\", ""), "\", "/")
Dim oFiles As String() = System.IO.Directory.GetFiles(sSubFolderPath)
For i As Integer = 0 To oFiles.Length - 1
Dim sFilePath As String = oFiles(i)
Dim oFileInfo As New System.IO.FileInfo(sFilePath)
Dim sFileName As String = oFileInfo.Name
Dim sSize As String = FormatNumber((oFileInfo.Length / 1024), 0)
If sSize = "0" AndAlso oFileInfo.Length > 0 Then sSize = "1"
Dim sImg As String = GetFileImg(sFileName)
Response.Write("<tr class='" & GetClassNameFromId(sFolderIds) & "' data-type='File' data-parent-id=""" & sFolderId & """ data-parent-ids=""" & sFolderIds & """>")
Response.Write("<td" & sIndentCss & ">")
'Response.Write("<span style='display:none'>" & sSubFolderPath & "</span>") ' for datatable sorting
Response.Write("<span style='display:none'>File</span>")
Response.Write("<img class='File' src='images/ext/" & sImg & "'> ")
Response.Write("<a href=""" & sSubFolderName & "/" & sFileName & """ target='_blank'>" & sFileName + "</a></td>")
Response.Write("<td>" & sSize & " KB</td>")
Response.Write("<td>" & oFileInfo.LastWriteTime.ToShortDateString() & " " & oFileInfo.LastWriteTime.ToShortTimeString() & "</td>")
Response.Write("<td><input type=checkbox name=chkDelete value=""" & Replace(sFilePath, sUploadFolderPath & "\", "") & """>")
Response.Write("</tr>")
Next
Dim oFolders As String() = System.IO.Directory.GetDirectories(sSubFolderPath)
For i As Integer = 0 To oFolders.Length - 1
Dim sSubSubFolderPath As String = oFolders(i)
Dim oFolderInfo As New IO.DirectoryInfo(sSubSubFolderPath)
Response.Write("<tr class='" & GetClassNameFromId(sFolderIds) & "' data-type='Folder' data-indent='" & iIndent & "' data-parent-id=""" & sFolderId & """ data-parent-ids=""" & sFolderIds & """ data-folder=""" & sSubSubFolderPath & """>")
Response.Write("<td" & sIndentCss & ">")
'Response.Write("<span style='display:none'>" & sSubSubFolderPath & "</span>") ' for datatable sorting
Response.Write("<span style='display:none'>Folder</span>")
Response.Write("<img src='images/plus.gif'class='Plus' onclick='ExpandFolder(this)'> ")
Response.Write("<img class='Folder' src='images/folder_closed.gif' onclick='ExpandFolder(this)'> ")
Response.Write("<span onclick='ExpandFolder(this)' class='FolderName'>" & oFolderInfo.Name + "</span></td>")
Response.Write("<td></td>")
Response.Write("<td>" & oFolderInfo.LastWriteTime.ToShortDateString() & " " & oFolderInfo.LastWriteTime.ToShortTimeString() & "</td>")
Response.Write("<td><input type=checkbox name=chkDeleteFolder value=""" & sSubSubFolderPath & """>")
Response.Write("</tr>")
Next
End Sub
Function GetClassNameFromId(ByVal sFolderIds As String) As String
Dim sRet As String = ""
Dim oFolderIds As String() = sFolderIds.Split(",")
For i As Integer = 0 To oFolderIds.Length - 1
sRet += " p" & oFolderIds(i)
Next
Return Trim(sRet)
End Function
Public Sub ShowFiles()
Dim sFolderPath As String = Server.MapPath(sFolder)
Dim oFiles As String() = System.IO.Directory.GetFiles(sFolderPath)
Dim oFolders As String() = System.IO.Directory.GetDirectories(sFolderPath)
If oFiles.Length = 0 And oFolders.Length = 0 Then
Exit Sub
End If
Response.Write("<table id='tbServer' class='table table-striped'>" & vbCrLf)
Response.Write("<thead><tr>" & vbCrLf)
Response.Write("<th>File name</th>")
Response.Write("<th>Size</th>")
Response.Write("<th>Date Modified</th>")
Response.Write("<th><label><input type=checkbox name=chkDeleteAll onclick='DeleteAll(this)'> Delete</label></th></tr></thead><tbody>")
For i As Integer = 0 To oFiles.Length - 1
Dim sFilePath As String = oFiles(i)
Dim oFileInfo As New System.IO.FileInfo(sFilePath)
Dim sFileName As String = oFileInfo.Name
Dim sSize As String = FormatNumber((oFileInfo.Length / 1024), 0)
If sSize = "0" AndAlso oFileInfo.Length > 0 Then sSize = "1"
Dim sImg As String = GetFileImg(sFileName)
Response.Write("<tr data-type='File'>")
Response.Write("<td><span style='display:none'>File</span><img class='File' src='images/ext/" & sImg & "'> ")
Response.Write("<a href=""" & sFolder & "/" & sFileName & """ target='_blank'>" & sFileName + "</a></td>")
Response.Write("<td>" & sSize & " KB</td>")
Response.Write("<td>" & oFileInfo.LastWriteTime.ToShortDateString() & " " & oFileInfo.LastWriteTime.ToShortTimeString() & "</td>")
Response.Write("<td><input type=checkbox name=chkDelete value=""" & sFileName & """>")
Response.Write("</tr>")
Next
For i As Integer = 0 To oFolders.Length - 1
Dim sSubFolderPath As String = oFolders(i)
Dim oFolderInfo As New IO.DirectoryInfo(sSubFolderPath)
Response.Write("<tr data-type='Folder' data-indent='0' data-folder=""" & sSubFolderPath & """>")
Response.Write("<td>")
'Response.Write("<span style='display:none'>" & sSubFolderPath & "</span>") ' for datatable sorting
Response.Write("<span style='display:none'>Folder</span>")
Response.Write("<img src='images/plus.gif'class='Plus' onclick='ExpandFolder(this)'> ")
Response.Write("<img class='Folder' src='images/folder_closed.gif' onclick='ExpandFolder(this)'> ")
Response.Write("<span onclick='ExpandFolder(this)' class='FolderName'>" & oFolderInfo.Name + "</span></td>")
Response.Write("<td></td>")
Response.Write("<td>" & oFolderInfo.LastWriteTime.ToShortDateString() & " " & oFolderInfo.LastWriteTime.ToShortTimeString() & "</td>")
Response.Write("<td><input type=checkbox name=chkDeleteFolder value=""" & sSubFolderPath & """>")
Response.Write("</tr>")
Next
Response.Write("</tbody></table>")
End Sub
Private Function GetFileImg(sFileName As String) As String
Dim sFileExt As String = GetExtFromFileName(sFileName)
Return GetFileExtImg(sFileExt)
End Function
Private Function GetFileExtImg(sFileExt As String) As String
Select Case LCase(Trim(sFileExt))
Case "bmp" : Return "bmp.gif"
Case "tif", "tiff" : Return "tif.png"
Case "doc", "rtf" : Return "doc.gif"
Case "exe", "bat" : Return "exe.gif"
Case "gif", "jpg", "png" : Return "gif.gif"
Case "htm", "tml" : Return "htm.gif"
Case "mdb" : Return "mdb.gif"
Case "mp3", "mpg", "avi", "mid" : Return "mp3.gif"
Case "mpp" : Return "mpp.gif"
Case "pdf" : Return "pdf.gif"
Case "ppt" : Return "ppt.gif"
Case "rpt" : Return "rpt.gif"
Case "txt" : Return "txt.gif"
Case "xls", "csv", "lsx" : Return "xls.gif"
Case "xml" : Return "xml.gif"
Case "zip", "cab" : Return "zip.gif"
Case "eml" : Return "eml.gif"
Case "swf" : Return "swf.gif"
Case "vsd" : Return "vsd.gif"
Case "xlt" : Return "xlt.gif"
Case "xls", "xlsx" : Return "xls.gif"
Case "doc", "docx" : Return "doc.gif"
Case "ppt", "pptx" : Return "ppt.gif"
Case "msg" : Return "ml.gif"
Case Else : Return "all.gif"
End Select
End Function
Private Function GetExtFromFileName(ByVal s As String) As String
If s = "" Then
Return ""
End If
Dim iPos As Integer = s.LastIndexOf(".")
If iPos = -1 Then
Return ""
End If
Return s.Substring(iPos + 1)
End Function
End Class