In MVC, the file upload function is implemented based on Ajax and HTML5,

Source: Internet
Author: User

In MVC, the file upload function is implemented based on Ajax and HTML5,

Introduction

In actual programming, you often encounter the function of uploading files and displaying the upload progress. For this purpose, this article describes how to upload files with progress display without using flash or any file upload plug-in.

Basic functions: implements the file upload function with a progress bar

Advanced features: You can upload multiple files by dragging files.

Background

HTML5 provides a standard method for accessing local files-File API specifications, which allow you to access File information by calling the File API, you can also use a client to verify whether the type and size of the uploaded file are standard.

This specification description contains the following interfaces to use files:

File interface: You can obtain the File name, type, and size with the "read permission" of the File.

FileList interface: A list of individually selected files. You can use <input type = "file"> or drag to display the list on the user interface.

XMLHTTPRequest2 is the unknown hero of HTML5. XHR2 and XMLHttpRequest are basically the same, but many new features are also added, as shown below:

1. added the upload/download of binary data

2. added a Progess (progress bar) event during the upload process. This event contains multiple parts of information:

Total: integer value, used to specify the Total number of bytes for data transmission.
Loaded: an integer that specifies the bytes to upload.
LengthComputable: Bool value is used to check whether the size of the uploaded file can be calculated.

3. Cross-resource sharing requests

These new features enable good collaboration between Ajax and HTML5, making File Upload very simple, without the use of Flash Player, external plug-ins, or html <form> labels, the upload progress bar is displayed based on the server.

This article will write a small application that can implement the following functions:

Upload a single file to display the upload progress.
Create a thumbnail when you send an image to the server.
You can upload multiple files through the file list or drag operation.
First, we need to check whether the browser supports XHR2, File API, FormData, and drag-and-drop operations.

Write code

How to upload a single file and display the upload progress?

First, you need to create a simple View:

Define a form that consists of the input file elements and the submit button.

Use the Bootstrap progress bar to display the progress.

<div id="FormContent">
        <form id="FormUpload"
        enctype="multipart/form-data" method="post">
          <span class="btn btn-success fileinput-button">
            <i class="glyphicon glyphicon-plus"></i>
            <span>Add files...</span>
            <input type="file"
            name="UploadedFile" id="UploadedFile" />
          </span>
          <button class="btn btn-primary start"
          type="button" id="Submit_btn">
            <i class="glyphicon glyphicon-upload"></i>
            <span>Start upload</span>
          </button>
          <button class="btn btn-warning cancel"
          type="button" id="Cancel_btn">
            <i class="glyphicon glyphicon-ban-circle"></i>
            <span>close</span>
          </button>
        </form>
        <div class="progress CustomProgress">
          <div id="FileProgress"
          class="progress-bar" role="progressbar"
      aria-valuenow="" aria-valuemin=""
      aria-valuemax="" style="width %;">
            <span></span>
          </div>
        </div>
        <div class="InfoContainer">
          <div id="Imagecontainer"></div>
          <div id="FileName" class="info">
          </div>
          <div id="FileType" class="info">
          </div>
          <div id="FileSize" class="info">
          </div>
        </div>
      </div>

Add an input file element to the Onchange event and use it in the JS method SingleFileSelected. Therefore, this method is called when you select and modify a file. In this method, we select the input file element and the file object accessing FileList, and select the first file files [0]. Therefore, we can get the file name, file type, and other information.

 function singleFileSelected(evt) {
     //var selectedFile = evt.target.files can use this or select input file element 
     //and access it's files object
     var selectedFile = ($("#UploadedFile"))[].files[];//FileControl.files[];
     if (selectedFile) {
       var FileSize = ;
       var imageType = /image.*/;
       if (selectedFile.size > ) {
         FileSize = Math.round(selectedFile.size * / ) / + " MB";
      }
      else if (selectedFile.size > ) {
        FileSize = Math.round(selectedFile.size * / ) / + " KB";
      }
      else {
        FileSize = selectedFile.size + " Bytes";
      }
      // here we will add the code of thumbnail preview of upload images
      
      $("#FileName").text("Name " + selectedFile.name);
      $("#FileType").text("type " + selectedFile.type);
      $("#FileSize").text("Size " + FileSize);
    }
  }

You can use the File reader object to read the uploaded File content from the memory. The reader object provides many events, including onload, onError, and four Data Reading functions: readAsBinaryString (), readAsText (), readAsArrayBuffer (), readAsDataURL (), and result. This attribute is valid only after the read operation is completed. The data format is determined based on the called initial read operation.

Here we will not describe File reader in detail. We will use it in the SingleFileSelected method to preview the image and view the Code:

 if (selectedFile.type.match(imageType)) {
        var reader = new FileReader();
        reader.onload = function (e) {
          $("#Imagecontainer").empty();
          var dataURL = reader.result;
          var img = new Image()
          img.src = dataURL;
          img.className = "thumb";
          $("#Imagecontainer").append(img);
        };
        reader.readAsDataURL(selectedFile);
      }

As of now, you can see:


Now you need to send the uploaded file to the server, so add The Onclick event and call it in the JS uploadFile () method. The Code is as follows:

function UploadFile() {
     //we can create form by passing the form to Constructor of formData object
     //or creating it manually using append function 
     //but please note file name should be same like the action Parameter
     //var dataString = new FormData();
     //dataString.append("UploadedFile", selectedFile);
   
     var form = $('#FormUpload')[];
     var dataString = new FormData(form);
    $.ajax({
      url '/Uploader/Upload', //Server script to process data
      type 'POST',
      xhr function () { // Custom XMLHttpRequest
        var myXhr = $.ajaxSettings.xhr();
        if (myXhr.upload) { // Check if upload property exists
          //myXhr.upload.onprogress = progressHandlingFunction
          myXhr.upload.addEventListener('progress', progressHandlingFunction, 
          false); // For handling the progress of the upload
        }
        return myXhr;
      },
      //Ajax events
      success successHandler,
      error errorHandler,
      completecompleteHandler,
      // Form data
      data dataString,
      //Options to tell jQuery not to process data or worry about content-type.
      cache false,
      contentType false,
      processData false
    });
  }

In this method, the Form is sent and the file value is serialized using the Form data object. We can manually create the formdata data Data instantiation and suspend the Domain value by calling the append () method, or retrieve the FormData object of the HTML form.

The progressHandlingFunction method checks whether the Size of the uploaded file can be calculated. e. loaded and e. total are used to calculate the amount of uploaded data.

function progressHandlingFunction(e) {
     if (e.lengthComputable) {
       var percentComplete = Math.round(e.loaded * / e.total);
       $("#FileProgress").css("width", 
       percentComplete + '%').attr('aria-valuenow', percentComplete);
       $('#FileProgress span').text(percentComplete + "%");
     }
     else {
       $('#FileProgress span').text('unable to compute');
    }
  }

Now we have implemented the basic data sending and progress bar functions. Next we need to implement code processing on the server side, using the upload action method and uplpader controller.

In the upload method, you can obtain the file information from the HttpPostedfileBase object. This object contains the basic information of the uploaded file, such as the Filename, Contenttype, and inputStream attributes, this information can be used to verify whether the file received by the server is incorrect or to save the file.

public JsonResult Upload(HttpPostedFileBase uploadedFile)
       {
         if (uploadedFile != null && uploadedFile.ContentLength > )
         {
           byte[] FileByteArray = new byte[uploadedFile.ContentLength];
           uploadedFile.InputStream.Read(FileByteArray, , uploadedFile.ContentLength);
           Attachment newAttchment = new Attachment();
          newAttchment.FileName = uploadedFile.FileName;
          newAttchment.FileType = uploadedFile.ContentType;
          newAttchment.FileContent = FileByteArray;
          OperationResult operationResult = attachmentManager.SaveAttachment(newAttchment);
          if (operationResult.Success)
          {
            string HTMLString = CaptureHelper.RenderViewToString
            ("_AttachmentItem", newAttchment, this.ControllerContext);
            return Json(new
            {
              statusCode = ,
              status = operationResult.Message,
              NewRow = HTMLString
            }, JsonRequestBehavior.AllowGet);
          }
          else
          {
            return Json(new
            {
              statusCode = ,
              status = operationResult.Message,
              file = uploadedFile.FileName
            }, JsonRequestBehavior.AllowGet);
          }
        }
        return Json(new
        {
          statusCode = ,
          status = "Bad Request! Upload Failed",
          file = string.Empty
        }, JsonRequestBehavior.AllowGet);
      }

Can I use the drag-and-drop operation to upload multiple files?

In this section, implement the same uploader and add some new features for uploader:

Multiple files can be selected
Drag operation
Now add new features to Uplodaer View:

Add multiple attributes to the input file element to select multiple files at the same time.

Add a file that implements the drag and drop function, as shown in the following code:

 <div id="drop_zone">Drop images Here</div>

Add the onChange event in the MultiplefileSelected JS method, which is similar to the SingleFileSelected method. The difference is that all files need to be listed and dragged. The Code is as follows:


function MultiplefileSelected(evt) {

    evt.stopPropagation();

    evt.preventDefault();

    $('#drop_zone').removeClass('hover');

    selectedFiles = evt.target.files || evt.dataTransfer.files;

    if (selectedFiles) {

      $('#Files').empty();

      for (var i = ; i < selectedFiles.length; i++) {

        DataURLFileReader.read(selectedFiles[i], function (err, fileInfo) {

         if (err != null) {

           var RowInfo = '<div id="File_' + i + '"

           class="info"><div class="InfoContainer">' +

                   '<div class="Error">' + err + '</div>' +

                  '<div data-name="FileName"

                  class="info">' + fileInfo.name + '</div>' +

                  '<div data-type="FileType"

                  class="info">' + fileInfo.type + '</div>' +

                  '<div data-size="FileSize"

                  class="info">' + fileInfo.size() +

                  '</div></div><hr/></div>';

           $('#Files').append(RowInfo);

         }

         else {

           var image = '<img src="' + fileInfo.fileContent +

           '" class="thumb" title="' +

           fileInfo.name + '" />';

           var RowInfo = '<div id="File_' + i + '"

           class="info"><div class="InfoContainer">' +

                  '<div data_img="Imagecontainer">' +

                  image + '</div>' +

                  '<div data-name="FileName"

                  class="info">' + fileInfo.name + '</div>' +

                  '<div data-type="FileType"

                  class="info">' + fileInfo.type + '</div>' +

                  '<div data-size="FileSize"

                  class="info">' + fileInfo.size() +

                  '</div></div><hr/></div>';

           $('#Files').append(RowInfo);

         }

       });

     }

   }

 }

In this method, the variables for selecting and dragging files are set as global variables selectedFiles, then each file in selectedfiles is scanned, and the Read method is called from the DataURLreader object to read the files.


The DataURLreader object can call the read method and take the File object and the callback method as the read method parameters. In the above method, we created the FileReader and modified the Onload and onerror callback functions of the FileReader. Call the readAsDataURL method to read the file.


The new FileInfo object includes all file information and content.


 var DataURLFileReader = {

     read function (file, callback) {

       var reader = new FileReader ();

       var fileInfo = {

         name file.name,

         type file.type,

         fileContent null,

         size function () {

           var FileSize =;

          if (file.size>) {

            FileSize = Math.round (file.size * /) / + "MB";

          }

          else if (file.size>) {

            FileSize = Math.round (file.size * /) / + "KB";

          }

          else {

            FileSize = file.size + "bytes";

          }

          return FileSize;

        }

      };

      if (! file.type.match ('image. *')) {

        callback ("file type not allowed", fileInfo);

        return;

      }

      reader.onload = function () {

        fileInfo.fileContent = reader.result;

        callback (null, fileInfo);

      };

      reader.onerror = function () {

        callback (reader.error, fileInfo);

      };

      reader.readAsDataURL (file);

    }

  };

Select using drag and drop

Since most browsers have now performed drag operations, in order to implement drag operations, add dragover and drop events to the drop_zone element.


         var dropZone = document.getElementById ('drop_zone');

         dropZone.addEventListener ('dragover', handleDragOver, false);

         dropZone.addEventListener ('drop', MultiplefileSelected, false);

         dropZone.addEventListener ('dragenter', dragenterHandler, false);

         dropZone.addEventListener ('dragleave', dragleaveHandler, false);


The dragover event is triggered when the file is dragged to the target position. In the following code, we have modified the dropEffect property of the default browser and datatransfer. The code is as follows:


  function handleDragOver (evt) {

     evt.preventDefault ();

     evt.dataTransfer.effectAllowed = 'copy';

     evt.dataTransfer.dropEffect = 'copy';

   }

Then add a drop event in MultiplefileSelected to handle the file drop operation.


Most of the functions have been improved. Now you need to add an "upload button" and call the UploadMultipleFiles method via the Onclick event.


This method is similar to the Uploadfile method mentioned above, except that the formdata object value is manually verified.


   function UploadMultipleFiles () {

     // here we will create FormData manually to prevent sending mon image files

     var dataString = new FormData ();

     // var files = document.getElementById ("UploadedFiles"). files;

     for (var i =; i <selectedFiles.length; i ++) {

       if (! selectedFiles [i] .type.match ('image. *')) {

         continue;

       }

      }

  // AJAX Request code here

  }

Next, add server-side processing code. Similar to the code added above, all you need to do is accept a list of files, as follows:


  public JsonResult UplodMultiple (HttpPostedFileBase [] uploadedFiles)

Make sure the HttpPostedFileBase array name is the same as the name in the append method, only then can MVC map to the file array.


 public JsonResult UplodMultiple (HttpPostedFileBase [] uploadedFiles)

  dataString.append ("uploadedFiles", selectedFiles [i]);

Upload large files

To allow large files to be uploaded, if you are using IIS7 and above, you need to modify the Web.config file and add the following code:


<system.webServer>

      <security>

           <requestFiltering>

                <requestLimits maxAllowedContentLength = "" />

           </ requestFiltering>

      </ security>

   </system.webServer>

   <httpRuntime targetFramework = "." maxRequestLength = "" />

All the functions can be realized here, and the maximum file size is 2GB.


The above content is the file upload function based on Ajax and HTML5 in MVC introduced by Xiaobian. I hope it will be helpful to everyone.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.