2011-03-03 56 views
16

我想在ASP.NET MVC中实现Gmail风格的拖放文件上传。文件API文件上传 - 读取ASP.NET MVC中的XMLHttpRequest

我一直在关注这篇文章:http://robertnyman.com/html5/fileapi-upload/fileapi-upload.html并希望将上传的文件发布到MVC控制器操作。

要做到这一点,我修改了样品中的链接的JavaScript脚本,指向我的控制器操作:

xhr.open("post", "/home/UploadFiles", true); 

这里是我的控制器操作:

[HttpPost] 
public virtual string UploadFiles(object obj) 
{ 
    var length = Request.ContentLength; 
    var bytes = new byte[length]; 
    Request.InputStream.Read(bytes, 0, length); 
    // var bytes has byte content here. what do do next? 

    return "Files uploaded!"; 
} 

我设置一个断点,当我上传一个文件时,断点会被打 - 这很好。但是,如何从上传的(javascript)XMLHttpRequest对象中提取数据?我不认为它在HttpRequest中 - 它是参数吗?如果是这样,我应该期待什么类型&如何提取字节数组并从中提取上传的文件信息?

(我使用的浏览器 - 我知道这并不在IE浏览器)

任何建议,将不胜感激!

回答

38

想通了。下面是C#代码:

[HttpPost] 
    public virtual string UploadFiles(object obj) 
    { 
     var length = Request.ContentLength; 
     var bytes = new byte[length]; 
     Request.InputStream.Read(bytes, 0, length); 
     // bytes has byte content here. what do do next? 

     var fileName = Request.Headers["X-File-Name"]; 
     var fileSize = Request.Headers["X-File-Size"]; 
     var fileType = Request.Headers["X-File-Type"]; 

     var saveToFileLoc = string.Format("{0}\\{1}", 
             Server.MapPath("/Files"), 
             fileName); 

     // save the file. 
     var fileStream = new FileStream(saveToFileLoc, FileMode.Create, FileAccess.ReadWrite); 
     fileStream.Write(bytes, 0, length); 
     fileStream.Close(); 

     return string.Format("{0} bytes uploaded", bytes.Length); 
    } 

而这里的Javascript代码:

<script type="text/javascript"> 
(function() 
{ 
    var filesUpload = document.getElementById("files-upload"); 
    var dropArea = document.getElementById("drop-area"); 
    var fileList = document.getElementById("file-list"); 

    function uploadFile(file) 
    { 
     var li = document.createElement("li"); 
     var progressBarContainer = document.createElement("div"); 
     var progressBar = document.createElement("div"); 

     progressBarContainer.className = "progress-bar-container"; 
     progressBar.className = "progress-bar"; 
     progressBarContainer.appendChild(progressBar); 
     li.appendChild(progressBarContainer); 

     // Uploading - for Firefox, Google Chrome and Safari 
     var xhr = new XMLHttpRequest(); 

     // Update progress bar 
     xhr.upload.addEventListener("progress", function (evt) 
     { 
      if (evt.lengthComputable) 
      { 
       progressBar.style.width = (evt.loaded/evt.total) * 100 + "%"; 
      } 
     }, false); 

     // File uploaded 
     xhr.addEventListener("load", function() 
     { 
      progressBarContainer.className += " uploaded"; 
      progressBar.innerHTML = "Uploaded!"; 
     }, false); 

     xhr.open("post", "/home/UploadFile", true); 

     // Set appropriate headers 
     xhr.setRequestHeader("Content-Type", "multipart/form-data"); 
     xhr.setRequestHeader("X-File-Name", file.fileName); 
     xhr.setRequestHeader("X-File-Size", file.fileSize); 
     xhr.setRequestHeader("X-File-Type", file.type); 

     // Send the file 
     xhr.send(file); 

     // Present file info and append it to the list of files 
     var div = document.createElement("div"); 
     li.appendChild(div); 
     var fileInfo = "<div><strong>Name:</strong> " + file.name + "</div>"; 
     fileInfo += "<div><strong>Size:</strong> " + parseInt(file.size/1024, 10) + " kb</div>"; 
     fileInfo += "<div><strong>Type:</strong> " + file.type + "</div>"; 
     div.innerHTML = fileInfo; 

     // insert at beginning of list. 
     fileList.insertBefore(li, fileList.firstChild); 

     // or insert at end of list. 
     //fileList.appendChild(li); 
    } 

    function traverseFiles(files) 
    { 
     if (typeof files !== "undefined") 
     { 
      for (var i = 0, l = files.length; i < l; i++) 
      { 
       uploadFile(files[i]); 
      } 
     } 
     else 
     { 
      fileList.innerHTML = "No support for the File API in this web browser"; 
     } 
    } 

    filesUpload.addEventListener("change", function() 
    { 
     traverseFiles(this.files); 
    }, false); 

    dropArea.addEventListener("dragleave", function (evt) 
    { 
     var target = evt.target; 

     if (target && target === dropArea) 
     { 
      this.className = ""; 
     } 
     evt.preventDefault(); 
     evt.stopPropagation(); 
    }, false); 

    dropArea.addEventListener("dragenter", function (evt) 
    { 
     this.className = "over"; 
     evt.preventDefault(); 
     evt.stopPropagation(); 
    }, false); 

    dropArea.addEventListener("dragover", function (evt) 
    { 
     evt.preventDefault(); 
     evt.stopPropagation(); 
    }, false); 

    dropArea.addEventListener("drop", function (evt) 
    { 
     //document.getElementById("file-list").innerHTML = ""; 

     traverseFiles(evt.dataTransfer.files); 
     this.className = ""; 
     evt.preventDefault(); 
     evt.stopPropagation(); 
    }, false); 
})(); 
+0

我假设保存请求byte []将是一个XML文档,而不是文件内容本身。结果比我预想的要简单得多。 – 2011-03-03 15:03:11

+2

+1用于保存我的傍晚 – Valentin 2011-03-14 15:51:33

+0

不错的代码。这是工作,WooHoo ~~~ – HorseKing 2012-01-23 19:37:59

0

这是伟大的。稍微改进:

xhr.setRequestHeader("X-File-Name", file.name); 
xhr.setRequestHeader("X-File-Size", file.size);