>  기사  >  웹 프론트엔드  >  MVC에서 Ajax와 HTML5 기반의 파일 업로드 기능 구현

MVC에서 Ajax와 HTML5 기반의 파일 업로드 기능 구현

亚连
亚连원래의
2018-05-24 16:27:442240검색

이 글은 MVC에서 Ajax와 HTML5 기반의 파일 업로드 기능에 대한 관련 정보를 주로 소개하고 있으니 필요하신 분들은 참고하시면 됩니다.

Introduction

실제 프로그래밍에서 우리는 파일 업로드와 구현 문제에 자주 부딪히게 됩니다. 업로드 진행 상황 표시 기능, 이 기사에서는 파일 업로드를 위한 플래시나 플러그인을 사용하지 않고 진행 상황 표시와 함께 파일 업로드 기능을 구현하는 방법을 소개합니다.

기본 기능: 진행률 표시줄을 사용하여 파일 업로드 기능 실현

고급 기능: 파일 드래그 앤 드롭으로 여러 파일 업로드 기능 실현

Background

HTML5는 로컬 파일에 액세스하는 표준 방법을 제공합니다 ——파일 API 사양. File API를 호출하여 정보에 접근할 수 있으며, 업로드된 파일의 형식과 크기가 표준화되어 있는지 클라이언트를 통해 확인할 수도 있습니다.

이 사양에는 파일을 사용하기 위한 다음 인터페이스가 포함됩니다.

파일 인터페이스: 파일에 대한 "읽기 권한"을 사용하면 파일 이름, 유형, 크기 등을 얻을 수 있습니다.

FileList 인터페이스: 3525558f8f338d4ea90ebf22e5cde2bc 또는 드래그 앤 드롭을 통해 사용자 선택을 위해 사용자 인터페이스에 표시될 수 있는 개별적으로 선택된 파일 목록을 나타냅니다.

XMLHTTPRequest2는 HTML5의 알려지지 않은 영웅입니다. XHR2는 XMLHttpRequest와 거의 동일하지만 다음과 같은 많은 새로운 기능도 추가합니다.

1. 업로드/다운로드 바이너리 데이터 추가

2. 업로드 프로세스) 이벤트, 여러 부분으로 구성된 정보:

Total: 전송된 데이터의 총 바이트 수를 지정하는 데 사용되는 정수 값입니다.
Loaded: 업로드된 바이트를 지정하는 데 사용되는 정수 값입니다.
lengthComputable: 업로드된 파일 크기가 계산 가능한지 여부를 감지하는 데 사용되는 부울 값입니다.

3. 리소스 간 공유 요청

이러한 새로운 기능을 사용하면 Ajax와 HTML5가 서로 잘 작동하므로 Flash Player, 외부 플러그인 또는 HTML의 ff9c23ada1bcecdd1a0fb5d5a0f18437 태그를 사용할 필요가 없습니다. 완료되면 업로드 진행률 표시줄이 서버 측에 표시됩니다.

이 기사에서는 다음 기능을 달성할 수 있는 작은 애플리케이션을 작성합니다.

단일 파일을 업로드하고 업로드 진행률 정보 표시를 제공합니다.
사진을 서버로 보낼 때 이미지 축소판을 만듭니다.
파일 목록 또는 드래그 앤 드롭 작업을 통해 여러 파일을 업로드하세요.
먼저 브라우저가 XHR2, File API, FormData 및 드래그 앤 드롭 작업을 지원하는지 확인해야 합니다.

코드 작성

단일 파일을 업로드하고 업로드 진행 상황을 표시하는 방법은 무엇입니까?

가장 먼저 해야 할 일은 간단한 보기를 만드는 것입니다.

입력 파일 요소와 제출 버튼으로 구성된 양식을 정의합니다.

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

파일 판독기 개체를 통해 메모리에서 업로드된 파일의 내용을 읽을 수 있습니다. reader 객체는 많은 이벤트, onload, onError 및 데이터 읽기를 위한 네 가지 함수(readAsBinaryString(), readAsText(), readAsArrayBuffer(), readAsDataURL())를 제공하고 결과 속성은 파일 내용을 나타냅니다. 이 속성은 읽기 작업이 완료된 후에만 유효하며, 데이터 형식은 호출된 초기화된 읽기 작업을 기반으로 결정됩니다.

여기에서는 파일 리더에 대해 자세히 설명하지 않겠습니다. 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
    });
  }

이 메서드에서는 다음을 보냅니다. 파일 값을 변환하려면 필드 값을 정지하기 위해 추가() 메소드를 호출하거나 HTML 양식의 FormData 객체를 검색하여 양식 데이터 데이터의 인스턴스화를 수동으로 생성할 수 있습니다.

progressHandlingFunction 메소드는 업로드된 파일 크기를 계산할 수 있는지 확인하는 메소드를 제공하고 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;);
    }
  }

이제 데이터 전송 및 진행률 표시줄 제공의 기본 기능이 구현되었으므로 업로드 작업 메서드와 uplpader 컨트롤러를 사용하여 서버 측 코드 처리를 구현해야 합니다.

업로드 방법에서는 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);
      }

드래그 앤 드롭 작업으로 여러 파일을 업로드할 수 있나요?


이 부분에서는 동일한 업로더를 구현하고 업로더에 몇 가지 새로운 기능을 추가합니다.

允许选择多个文件
拖拽操作
现在给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으로 문의하세요.