Это сложно, но не невозможно.Идея: разрезать файл на куски на стороне клиента и отправить его по частям.На сервере объединяем куски.Это рабочий пример.
Клиент:
<input type="file" id="inFile" />
<button id="btnSend" type="button">Upload</button>
<script>
document.getElementById('btnSend').addEventListener('click', function () {
var chunkSize = 200; //small for test purpose. Set below limit
var fu = document.getElementById('inFile');
if (!fu.files) return;
var reader = new FileReader();
reader.onload = function () {
var bytes = this.result.split('').map(function (b) { return b.charCodeAt(); });
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
var b = bytes.splice(0, chunkSize);
if (b.length) {
//repeat until EOF
xhr.open('POST', 'img-upload.ashx', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('fn=' + fu.files[0].name + '&bytes=' + b);
}
}
};
xhr.open('POST', 'img-upload.ashx', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); //required to use Request.Form on the server
xhr.send('fn=' + fu.files[0].name + '&bytes=' + bytes.splice(0, chunkSize) + '&chunk=0'); //mark 1st chunk
}
reader.readAsBinaryString(fu.files[0]);
});
</script>
Сервер:
Я использовал общий обработчик ASP.NET (.ashx)здесь.
using System;
using System.Web;
using System.Linq;
public class img_upload : IHttpHandler {
public void ProcessRequest (HttpContext context) {
string[] strBytes = ((string)context.Request.Form["bytes"]).Split(',');
byte[] bytes = strBytes.Select(b => Convert.ToByte(b)).ToArray();
string fileName = context.Server.MapPath("~/misc/img/" + (string)context.Request.Form["fn"]); //make sure the process has write permission
System.IO.FileStream fs = null;
if (context.Request.Form["chunk"] == "0")//first chunk
{
fs = new System.IO.FileStream(fileName, System.IO.FileMode.Create);
}
else
{
fs = new System.IO.FileStream(fileName, System.IO.FileMode.Append);
}
fs.Write(bytes, 0, bytes.Length);
fs.Close();
context.Response.ContentType = "text/plain"; //or whatever
context.Response.Write("OK");//or whatever
}
public bool IsReusable {
get {
return false;
}
}
}