ASP.NET MVC - Single File and Multi-File Upload and Download Management

I have written an article on the ASP.NET method about how to download documents from a database (Traditional Chinese); however, there are some defects as a result of this method. For example, because of the binary file, it takes up a huge space of the database, even after zipping the documents. Moreover, if your framework is separated into web application and database servers, the bandwidth and I/O costs will grow.

Let’s do this in a different way; upload a file to Web Application under a specific folder. Then, save this information to the database. This information is text, so it won’t impact the efficiency of the database server. Even if you have billions of records, your database will still work efficiently. When you need to download a document (file), your query information from the database will map to the specific folder (file) and respond to the client browser.

Based on the ASP.NET MVC implement, it will contain two parts: one is single file upload, one is the multi-file upload.

DataBase Schema

I create a new file in the App_Data in Files.mdf, table name called FileDown, and table Schema is:

FileId, int, PK
FileName, nvarchar(50)
FileSize, nvarchar(50)
FileType, nvarchar(50)
FileVersion, nvarchar(50)
PostDate, datetime2(7)
UploadDate, datetime2(7)
rowguid, uniqueidentifier

In the Models folder, I create FileModel.edmx and FileModel.Context.tt, FileModel.tt. (Entity Framework 4.1)

ASP.NET MVC - Single File Upload

Create a New FileController.vb and write down our architecture.

Controller and Action : fileController.vb

Imports System.IO

Public Class fileController
    Inherits System.Web.Mvc.Controller

    ' File Lists
    Function Index() As ActionResult
        Return View()
    End Function

    ' Single File Upload
    Function Upload() As ActionResult
        Return View()
    End Function

    ' Single File Save
    <HttpPost()>
    Function Upload(upfile As HttpPostedFileBase, formData As FormCollection) As ActionResult
        Return View()
    End Function

    ' Multi-File Upload
    Function MultiUpload() As ActionResult
        Return View()
    End Function

    ' Multi-File Save
    <HttpPost()>
    Function MultiUpload(form As FormCollection) As ActionResult
        Return View()
    End Function

    ' File Download
    Function Download(id As Integer) As ActionResult
        Return View()
    End Function
End Class

We work step by step.

Action:Index


' File Lists
Function Index() As ActionResult
    Dim db As New FilesEntities
    Return View(db.FileDown)
End Function

View : Index.aspx


<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of UpDownFileFromDBMvc.FileDown))" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    File Lists
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>File Lists</h2>
<ul>
    <li><%: Html.ActionLink("Single File Upload", "Upload")%></li>
    <li><%: Html.ActionLink("Multi-File Upload", "MultiUpload")%></li>
</ul>
<table>
    <tr>
        <th>
            FileId
        </th>
        <th>
            FileName
        </th>
        <th>
            FileSize
        </th>
        <th>
            FileType
        </th>
        <th>
            FileVersion
        </th>
        <th>
            PostDate
        </th>
        <th>
            UploadDate
        </th>
        <th>
            rowguid
        </th>
    </tr>

<% For Each item In Model %>
    <% Dim currentItem = item %>
    <tr>
        <td>
            <%: Html.DisplayFor(Function(modelItem) currentItem.FileId) %>
        </td>
        <td>
            <%: Html.ActionLink(currentItem.FileName, "download", New With {.id = currentItem.FileId})%>
        </td>
        <td>
            <%: Html.DisplayFor(Function(modelItem) currentItem.FileSize) %>
        </td>
        <td>
            <%: Html.DisplayFor(Function(modelItem) currentItem.FileType) %>
        </td>
        <td>
            <%: Html.DisplayFor(Function(modelItem) currentItem.FileVersion) %>
        </td>
        <td>
            <%: Html.DisplayFor(Function(modelItem) currentItem.PostDate) %>
        </td>
        <td>
            <%: Html.DisplayFor(Function(modelItem) currentItem.UploadDate) %>
        </td>
        <td>
            <%: Html.DisplayFor(Function(modelItem) currentItem.rowguid) %>
        </td>
    </tr>
<% Next %>
</table>
</asp:Content>

We should notice that there is <%: Html.ActionLink(currentItem.FileName, "download", New With {. Id = currentItem.FileId})%>. After uploading, we hope to click the file name and download the file directly, so we have the DisplayFor() rewritten toHtml.ActionLink().

Action:Upload


''' <summary>
''' ASP.NET MVC Single File Upload
''' </summary>
''' <param name="upfile">Upload file</param>
''' <param name="formData">Other file data</param>
<HttpPost()>
Function Upload(upfile As HttpPostedFileBase, formData As FormCollection) As ActionResult
    Using db As New FilesEntities
 
        If upfile IsNot Nothing Then
            ' 0 < Size < 4 MB
            Dim MBSize As Integer = upfile.ContentLength / 1000 / 1000
            If upfile.ContentLength > 0 AndAlso MBSize < 4 Then
                Dim savePath As String = Path.Combine(Server.MapPath("~/Files/"), upfile.FileName)

                ' Only *.7z file name
                If Path.GetExtension(savePath) <> ".7z" Then
                    ModelState.AddModelError("upfile", "File name only *.7z!")
                    Return View()
                End If

                ' Date Check
                If IsDate(formData("PostDate")) = False Then
                    ModelState.AddModelError("PostDate", "Date Format Is Error!")
                    Return View()
                End If

                ' Version Check
                If formData("FileVersion") = "" Then
                    ModelState.AddModelError("FileVersion", "Must have file version!")
                    Return View()
                End If

                ' Uploading
                If System.IO.File.Exists(savePath) = False Then

                    ' Database Checking
                    Dim FileDuplicate As FileDown = (From f In db.FileDown
                                                     Where (f.FileName = upfile.FileName)
                                                     Select f).FirstOrDefault()

                    ' File name checking
                    If FileDuplicate Is Nothing Then
                        ' Save to Disk
                        upfile.SaveAs(savePath)

                        ' Set File Information
                        Dim file As New FileDown
                        file.FileName = upfile.FileName
                        file.FileSize = upfile.ContentLength
                        file.FileType = upfile.ContentType
                        file.PostDate = formData("PostDate")
                        file.FileVersion = formData("FileVersion")
                        file.UploadDate = Date.Now()
                        file.rowguid = Guid.NewGuid()

                        ' File Information Save to Database
                        db.FileDown.Add(file)
                        db.SaveChanges()
                    Else
                        ModelState.AddModelError("upfile", "Database have same file information!")
                        Return View()
                    End If
                Else
                    ModelState.AddModelError("upfile", "File exist!")
                    Return View()
                End If
            End If
        End If
    End Using

    Return RedirectToAction("Index")
End Function

We create a Files folder in the project to store uploaded files. Here we should notice that the parameters passed in sequential order, Upload.aspx order form, if the upload file field first, then upfile As HttpPostedFileBase necessary in the first, and vice versa.

View:Upload.aspx


<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Upload Single File
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Upload Single File</h2>

<%Using Html.BeginForm("Upload", "file", FormMethod.Post, New With {.enctype = "multipart/form-data"})%>
    <%: Html.ValidationSummary(True)%>
    File:<input id="upfile" name="upfile" type="file" value="" />
          <%: Html.ValidationMessage("upfile")%>
 
    PostDate:<%: Html.TextBox("PostDate")%>
          <%: Html.ValidationMessage("PostDate")%>
 
    Version:<%: Html.TextBox("FileVersion")%>
          <%: Html.ValidationMessage("FileVersion")%>
 
    <input type="submit" value="Upload" />
<%End Using%>

</asp:Content>

ASP.NET MVC Multi-File Upload

Next let’s take a look at the multi-file uploads.

Action:MultiUpload


''' <summary>
''' ASP.NET MVC Multi-File Upload
''' </summary>
''' <param name="form">form data</param>
<HttpPost()>
Function MultiUpload(form As FormCollection) As ActionResult
    ' Data Check Reference "Action:Upload"

    Dim Msg As String = String.Empty
    For i As Integer = 0 To Request.Files.Count - 1
        Msg += Request.Files(i).FileName & " Upload succeed!"
        Request.Files(i).SaveAs(Server.MapPath("~/Files/") & Request.Files(i).FileName)
    Next

    ViewBag.Msg = MvcHtmlString.Create(Msg)

    Return View()
End Function

Let me skip some steps, check the files and add information to the database are almost the same with we have mentioned above. Now you try to do it yourself.

View:MultiUpload.aspx


<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Multi-File Upload 
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Multi-File Upload</h2>
<%: Html.ActionLink("Go back Index","Index") %>
<% Using (Html.BeginForm("MultiUpload", "File", FormMethod.Post, New With {.enctype = "multipart/form-data"}))%>
        <div class="uploadfiles">
            <p>
                <input type="file" name="files" />
            </p>
        </div>
        <p>
            <a href="#add" id="additem">Add Upload File</a>
            <input type="submit" value="Upload" />
        </p>
<% End Using%>

<%: ViewBag.Msg %>
<script type="text/javascript">
    $('#additem').live('click', function () {
        $('.uploadfiles').append($("<p><input type='file' name='files' /></p>"));
    });
</script>
</asp:Content>

The most important part is the bellowing jQuery, let us re-state to upload new data fields.

ASP.NET MVC File Download

The last download program.

Action:Download


Function Download(id As Integer) As ActionResult
    Using db As New FilesEntities
        ' Get file information
        Dim getfile = (From f In db.FileDown
                       Where f.FileId = id
                       Select f).FirstOrDefault()

        If getfile.FileName IsNot Nothing Then
            Dim FilePath As String = Server.MapPath("~/Files/" & getfile.FileName)

            ' downloading
            If System.IO.File.Exists(FilePath) Then
                Return File(FilePath, getfile.FileType, getfile.FileName)
            End If
        Else
            ' response error
            Return Content("<span style='color:red'>Can't download file!</span>")
        End If
    End Using

    Return RedirectToAction("Index")
End Function

We design a table with GUID, you can also use the GUID to design a method for users to download, so users can not guess easily like 1,2,3,4 number to download data.

ASP.NET MVC File Delete

Skip some steps for you to write here.
  1. Query the id from the database to find the file name.
  2. Use Path.Combine and Server.MapPath () to combine the full path.
  3. Use File.Exists (path) to determine whether the file exists.
  4. If it exists, delete files and database information.(File.Delete (path))
Now an uploading, downloading, deleting, simple file management program is completed.

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。