文件 API 文件上传 - 在 ASP.NET MVC 中读取 XMLHttpRequest
Posted
技术标签:
【中文标题】文件 API 文件上传 - 在 ASP.NET MVC 中读取 XMLHttpRequest【英文标题】:File API File Upload - Read XMLHttpRequest in ASP.NET MVC 【发布时间】:2011-07-08 02:18:52 【问题描述】:我正在尝试在 ASP.NET MVC 中实现 Gmail 样式的拖放文件上传。
我一直在关注这篇文章: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 - 它是参数吗?如果是这样,我应该期望什么类型以及如何提取字节数组并从中提取上传的文件信息?
(我使用的是 Chrome - 我知道它在 IE 中不起作用)
任何建议将不胜感激!
【问题讨论】:
【参考方案1】:想通了。这是 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);
)();
【讨论】:
我假设保存请求 byte[] 将是一个 XML 文档,而不是文件内容本身。结果比我预期的要简单得多。 当我尝试使用此代码时。如果我尝试上传图片,我会得到错误的文件 @WeekendWarrior 当我尝试上传图像时,您添加的标题已存储在图像中。如何从文件中删除这些标题? 请注意,您不需要发送X-File-Size
标头,因为Request.ContentLength
包含文件的长度。【参考方案2】:
这很棒。略有改进:
xhr.setRequestHeader("X-File-Name", file.name);
xhr.setRequestHeader("X-File-Size", file.size);
【讨论】:
以上是关于文件 API 文件上传 - 在 ASP.NET MVC 中读取 XMLHttpRequest的主要内容,如果未能解决你的问题,请参考以下文章
在 ASP.NET Core Web API 中上传文件和 JSON
仅在文件上传中出现 Asp.Net Core API CORS 策略错误