搜尋
首頁web前端js教程MVC中基於Ajax與HTML5實作檔案上傳功能

這篇文章主要介紹了MVC中基於Ajax和HTML5實現文件上傳功能的相關資料,需要的朋友可以參考下

引言

在實際程式設計中,經常遇到實作檔案上傳並顯示上傳進度的功能,基於此目的,本文就為大家介紹不使用flash 或任何上傳檔案的插件來實現具有進度顯示的檔案上傳功能。

基本功能:實現具有進度條的檔案上傳功能

#進階功能:透過拖曳檔案的操作實現多個檔案上傳功能

##背景

HTML5提供了一種標準的存取本機檔案的方法—File API規格說明,透過呼叫File API 能夠存取檔案信息,也可以利用客戶端來驗證上傳檔案的類型和大小是否規範。

此規格說明包含以下幾個介面來使用檔案:

File介面:具有檔案的“讀取權限”,可以取得檔案名,類型,大小等。

FileList介面:指單獨選定的文件列表,可以透過或拖曳呈現在使用者介面供使用者選擇。

XMLHTTPRequest2是HTML5的無名英雄,XHR2與XMLHttpRequest大體相同,但同時也增加了許多新功能,如下:

##1. 增加了上傳/下載二進位資料

2. 增加了上傳過程中Progess (進度條)事件,該事件包含多部分的資訊:

Total:整數值,用於指定傳輸資料的總位元組數。

Loaded:整數值,用於指定上傳的位元組。

lengthComputable:Bool值用來偵測上傳檔案大小是否可計算。

3. 跨資源共享請求

這些新功能都使得Ajax和HTML5很好的協作,讓檔案上傳變得非常簡單,不再需要使用Flash Player、外部外掛程式或html的

標籤就可以完成,依照伺服器端就可以顯示上傳進度列。

本文會編寫一個小型應用程序,能夠實現以下功能:

上傳單一文件,提供上傳進度資訊顯示。

將圖片傳送到伺服器時,建立圖像縮圖。

透過檔案清單或拖曳操作實現多個檔案上傳。
首先我們需要檢驗瀏覽器是否支援XHR2,File API,FormData及拖曳操作。

編寫程式碼

如何上傳單一檔案並顯示上傳進度?


首先需要做的是建立簡單的View :

定義一個表單,由輸入檔案元素和提交按鈕組成。


使用Bootstrap 進度條顯示進度。


<p 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>
        <p class="progress CustomProgress">
          <p id="FileProgress"
          class="progress-bar" role="progressbar"
      aria-valuenow="" aria-valuemin=""
      aria-valuemax="" style="width %;">
            <span></span>
          </p>
        </p>
        <p class="InfoContainer">
          <p id="Imagecontainer"></p>
          <p id="FileName" class="info">
          </p>
          <p id="FileType" class="info">
          </p>
          <p id="FileSize" class="info">
          </p>
        </p>
      </p>

在Onchange 事件中新增輸入檔案元素,並在JS方法SingleFileSelected使用,因此在使用者選擇和修改檔案時都會呼叫此方法。在這個方法中,我們將選擇輸入文件元素和存取FileList的文件對象,選擇第一個文件files[0],因此我們可以得到文件名,文件類型等資訊。

 function singleFileSelected(evt) {
     //var selectedFile = evt.target.files can use this or select input file element 
     //and access it&#39;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);
    }
  }

可以透過File reader物件從記憶體讀取上傳檔案內容。 reader 物件提供許多事件,onload,onError以及四種讀取資料的函數readAsBinaryString(), readAsText(),readAsArrayBuffer(), readAsDataURL(),result屬性表示檔案內容。此屬性只有當讀取操作執行完成後才有效,資料格式根據所呼叫的初始化讀取操作制定的。

在這裡就不詳細解釋File reader,我們會在SingleFileSelected 方法中使用,用於預覽圖像,查看程式碼:

##

 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);
      }

#到目前為止,就可以看到下圖:

現在需要將已上傳的檔案傳送到伺服器,因此新增Onclick事件,並在JS uploadFile()方法中調用,程式碼如下:

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 = $(&#39;#FormUpload&#39;)[];
     var dataString = new FormData(form);
    $.ajax({
      url &#39;/Uploader/Upload&#39;, //Server script to process data
      type &#39;POST&#39;,
      xhr function () { // Custom XMLHttpRequest
        var myXhr = $.ajaxSettings.xhr();
        if (myXhr.upload) { // Check if upload property exists
          //myXhr.upload.onprogress = progressHandlingFunction
          myXhr.upload.addEventListener(&#39;progress&#39;, 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
    });
  }

在該方法中,發送表單,使用Form 資料物件來序列化檔案值,我們可以手動建立formdata資料的實例化,透過呼叫append()方法將域值掛起,或透過檢索HTML 表單的FormData物件。

progressHandlingFunction方法會提供檢驗上傳檔案Size 是否可計算,使用e.loaded和e.total計算出已上傳百分之多少的資料。

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

現在已經實作了基本的發送資料及提供進度條的功能,接下來需要實作伺服器端的程式碼處理,使用upload action方法和uplpader controller 。

在upload 方法中,可以從HttpPostedfileBase物件中取得文件訊息,該物件包含上傳的檔案的基本資訊如Filename屬性,Contenttype屬性,inputStream屬性等內容,這些資訊都可以用來驗證伺服器端接收的文件是否有錯,也可以用來保存文件。        

 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);
      }

 能否透過拖曳操作來實現多個檔案上傳的功能?

在這一部分,實作相同的uploader,並為uploader添加一些新功能:

允许选择多个文件
拖拽操作
现在给Uplodaer View添加新功能:

为输入文件元素添加多个属性,实现同时选择多个文件。

添加实现拖拽功能的文件,如以下代码所示:

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

在JS方法MultiplefileSelected中添加onChange事件,与之前SingleFileSelected的写法类似,不同的是需要将所有的文件列出,并允许拖拽文件。代码如下:

 function MultiplefileSelected(evt) {
     evt.stopPropagation();
     evt.preventDefault();
     $(&#39;#drop_zone&#39;).removeClass(&#39;hover&#39;);
     selectedFiles = evt.target.files || evt.dataTransfer.files;
     if (selectedFiles) {
       $(&#39;#Files&#39;).empty();
       for (var i = ; i < selectedFiles.length; i++) {
         DataURLFileReader.read(selectedFiles[i], function (err, fileInfo) {
          if (err != null) {
            var RowInfo = &#39;<p id="File_&#39; + i + &#39;" 
            class="info"><p class="InfoContainer">&#39; +
                    &#39;<p class="Error">&#39; + err + &#39;</p>&#39; +
                   &#39;<p data-name="FileName" 
                   class="info">&#39; + fileInfo.name + &#39;</p>&#39; +
                   &#39;<p data-type="FileType" 
                   class="info">&#39; + fileInfo.type + &#39;</p>&#39; +
                   &#39;<p data-size="FileSize" 
                   class="info">&#39; + fileInfo.size() + 
                   &#39;</p></p><hr/></p>&#39;;
            $(&#39;#Files&#39;).append(RowInfo);
          }
          else {
            var image = &#39;<img src="&#39; + fileInfo.fileContent + 
            &#39;" class="thumb" title="&#39; + 
            fileInfo.name + &#39;" />&#39;;
            var RowInfo = &#39;<p id="File_&#39; + i + &#39;" 
            class="info"><p class="InfoContainer">&#39; +
                   &#39;<p data_img="Imagecontainer">&#39; + 
                   image + &#39;</p>&#39; +
                   &#39;<p data-name="FileName" 
                   class="info">&#39; + fileInfo.name + &#39;</p>&#39; +
                   &#39;<p data-type="FileType" 
                   class="info">&#39; + fileInfo.type + &#39;</p>&#39; +
                   &#39;<p data-size="FileSize" 
                   class="info">&#39; + fileInfo.size() + 
                   &#39;</p></p><hr/></p>&#39;;
            $(&#39;#Files&#39;).append(RowInfo);
          }
        });
      }
    }
  }

在该方法中,将选择和拖拽文件操作的变量设置为全局变量selectedFiles,然后扫描 selectedfiles中的每个文件,将从 DataURLreader对象中调用Read 方法读取文件。

DataURLreader对象可调用read方法,并将File对象和回调方法作为read方法参数,在上述方法中我们创建了FileReader,并修改了FileReader的Onload和onerror回调函数。调用 readAsDataURL 方法来读文件。

新建FileInfo对象包括了所有的文件信息及内容。

 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(&#39;image.*&#39;)) {
        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);
    }
  };

使用拖拽操作选择

由于大部分浏览器现在已经执行拖拽操作,为了实现拖拽操作,在drop_zone 元素中添加dragover和drop事件。

         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);

当文件拖到目标位置时触发dragover事件,在以下代码中,我们修改了默认浏览器及datatransfer的dropEffect 属性,代码如下:

  function handleDragOver(evt) {
     evt.preventDefault();
     evt.dataTransfer.effectAllowed = &#39;copy&#39;;
     evt.dataTransfer.dropEffect = &#39;copy&#39;;
   }

接着在MultiplefileSelected中添加drop事件来处理文件drop操作。

大部分功能已经完善,现在需要添加“上传按钮”,通过Onclick事件来调用UploadMultipleFiles方法。

该方法与上文提到的Uploadfile方法类似,不同的是手动验证formdata对象值。

   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(&#39;image.*&#39;)) {
         continue;
       }
      }
  // AJAX Request code here
  }

接下来添加服务器端处理代码,与上文添加的代码类似,需要做的就是接受一系列的文件列表,如下:

  public JsonResult UplodMultiple(HttpPostedFileBase[] uploadedFiles)

确保 HttpPostedFileBase 数组名称与append 方法中的名称相同,只有这样,MVC才能映射到文件数组中。

 public JsonResult UplodMultiple(HttpPostedFileBase[] uploadedFiles)
  dataString.append("uploadedFiles", selectedFiles[i]); 

上传大文件

为了允许上传大文件,如果使用的是 IIS7及以上版本,需要修改Web.config 文件,添加以下代码:

<system.webServer>
      <security>
           <requestFiltering>
                <requestLimits maxAllowedContentLength="" />
           </requestFiltering>
      </security>
   </system.webServer>
   <httpRuntime targetFramework="." maxRequestLength=""/>

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

初步了解JavaScript,Ajax,jQuery,并比较三者关系

jquery与php结合实现AJAX长轮询

js ajax加载时的进度条代码

以上是MVC中基於Ajax與HTML5實作檔案上傳功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

node.js流帶打字稿node.js流帶打字稿Apr 30, 2025 am 08:22 AM

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python vs. JavaScript:性能和效率注意事項Python vs. JavaScript:性能和效率注意事項Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript的起源:探索其實施語言JavaScript的起源:探索其實施語言Apr 29, 2025 am 12:51 AM

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

幕後:什麼語言能力JavaScript?幕後:什麼語言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。