前言:

大文件传输一直是技术上的一大难点。文件过大时,一些性提交所有的内容进内存是不现实的。大文件带来问题还有是否支持断点传输和多文件同时传输。

本文以resumableJs为例,介绍了如何在ASP.NET中实现大文件传输。同时本文利用了Html5的新特性:支持拖拽。

本文的主要技术点在于:如何接收resumableJs的传送内容(官网不太清楚)和如何合并文件,难度并不高。如果要改为MVC中的Controller处理文件传输,方法也大同小异。

注:原博客中,此文章在原站点个人代码备份所用,注释不多,如有不懂,请在评论中给出。

效果

ASPX File:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server"><title>Resumable.js Test</title>
</head>
<body><form id="form1" runat="server">     <div id="container" style="width:300px;height:200px;background-color:lightgray">        </div></form><span id="info">welcome</span><script src="scripts/resumable.js" type="text/javascript"></script><script  type="text/javascript">var showInfo = function (msg) {document.getElementById("info").innerHTML = msg;}showInfo("Test begin");var r = new Resumable({target: 'FileHandler.ashx',});r.assignBrowse(document.getElementById('container'));r.assignDrop(document.getElementById('container'));if (!r.support) showInfo("not support");r.on('fileAdded', function (file, event) {r.upload();});r.on('filesAdded', function (array) {for (var i = 0; i < array.length; i++) {var html = document.getElementById("info").innerHTML;html += "<br>"+array[i].name;}});r.on('uploadStart', function () {showInfo('start');});r.on('complete', function () {r.files.pop(); //if want to upload one file multiple times, you should remove it from r.files after completing.//pop后,才可再次重新拖拽上传此文件。此机制可避免一次上传多个文件时重复添加,但拖拽上传时不用检测。});r.on('progress', function (e) {showInfo(r.progress());});</script>
</body>
</html>

FileHandler

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;namespace UploadTest
{/// <summary>/// Summary description for FileHandler/// </summary>public class FileHandler : IHttpHandler{string _tempFolder;object _lock = new object();public void ProcessRequest(HttpContext context){_tempFolder = context.Server.MapPath("~/temp");var method = context.Request.HttpMethod;if (method.Equals("GET")){HandleGet(context);}if (method.Equals("POST")){HandlePost(context);}}private  void HandlePost(HttpContext context){var queryString = context.Request.Form;if (queryString.Count == 0) return;try{// Read parametersvar uploadToken = queryString.Get("upload_Token");int resumableChunkNumber = int.Parse(queryString.Get("resumableChunkNumber"));var resumableTotalChunks = int.Parse(queryString.Get("resumableTotalChunks"));var resumableTotalSize = long.Parse(queryString.Get("resumableTotalSize"));                var resumableFilename = queryString.Get("resumableFilename");// Save Fileif (context.Request.Files.Count == 0){context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; }else{var filePath = string.Format("{0}/{1}/{1}.part{2}", _tempFolder, resumableFilename, resumableChunkNumber.ToString("0000"));var directory = Path.GetDirectoryName(filePath);if (File.Exists(directory)){File.Delete(directory);}if (!Directory.Exists(directory)){Directory.CreateDirectory(directory);}if (!System.IO.File.Exists(filePath)){context.Request.Files[0].SaveAs(filePath);}if (IsCompleted(directory,resumableTotalChunks,resumableTotalSize)){MergeFiles(directory);}}}catch (Exception exception){throw exception;}}private void HandleGet(HttpContext context){var queryString = context.Request.QueryString;if (queryString.Count == 0) return;try{// Read parametersvar uploadToken = queryString.Get("upload_Token");int resumableChunkNumber = int.Parse(queryString.Get("resumableChunkNumber"));var resumableFilename = queryString.Get("resumableFilename");var resumableChunkSize = long.Parse(queryString.Get("resumableChunkSize")); var filePath = string.Format("{0}/{1}/{1}.part{2}", _tempFolder,resumableFilename, resumableChunkNumber.ToString("0000")); // Check for existance and chunksize if (System.IO.File.Exists(filePath) && new FileInfo(filePath).Length == resumableChunkSize){context.Response.Status = "200 OK";context.Response.StatusCode = 200; }else{context.Response.Status = "404 Not Found";context.Response.StatusCode = 404;}}catch (Exception exception){throw exception;}}private bool IsCompleted(string directory,int numChunks, long totalSize ){var physicalFolder = Path.Combine(_tempFolder, directory);var files = Directory.GetFiles(physicalFolder);//numbersif (files.Length != numChunks)return false;//files all exisitvar fileName = Path.GetFileName(directory);for (int i = 1; i <= numChunks; i++){var filePath = string.Format("{0}/{1}.part{2}", directory, fileName, i.ToString("0000"));if (!File.Exists(filePath)){return false;}}//size long tmpSize = 0;foreach (var file in files){tmpSize += new FileInfo(file).Length;} return totalSize==tmpSize;}private void MergeFiles(string directoryPath){      lock (_lock){if (Directory.Exists(directoryPath)){var fileName = Path.GetFileName(directoryPath);var folder = Path.GetDirectoryName(directoryPath);var tempPath = Path.Combine(directoryPath + ".tmp");var files = Directory.GetFiles(directoryPath);files = files.OrderBy(f => f).ToArray();FileStream wholeStream = new FileStream(tempPath, FileMode.Append, FileAccess.Write);for(int i=0;i<files.Length;i++){    FileStream parcialStream = new FileStream(files[i], FileMode.Open);BinaryReader parcialReader = new BinaryReader(parcialStream);byte[] buffer = new byte[parcialStream.Length];buffer = parcialReader.ReadBytes((int)parcialStream.Length);BinaryWriter parcialWriter = new BinaryWriter(wholeStream);parcialWriter.Write(buffer);parcialStream.Close();}wholeStream.Close();Directory.Delete(directoryPath,true);File.Move(tempPath, directoryPath);                     }}                             }public bool IsReusable{get{return false;}} }
}

附录:

1 技术难点

a. 文件过大。修改webconfig无用。

b. 断点续传。

c. 多文件上传。

2 resumable.js

API: http://www.resumablejs.com/

工作流程:

拖文件至DIV -> 开始上传,uploadStart -> 反复触发progress事件 -> compete

主要参数:

Get:

resumableChunkNumber=1&
resumableChunkSize=1048576&
resumableCurrentChunkSize=1048576&
resumableTotalSize=27778318&
resumableType=&
resumableIdentifier=27778318-Samples7z&
resumableFilename=Samples.7z&
resumableRelativePath=Samples.7z&
resumableTotalChunks=26

Post:

—————————–111061030216033
Content-Disposition: form-data; name=”resumableChunkNumber”

140
—————————–111061030216033
Content-Disposition: form-data; name=”resumableChunkSize”

1048576
—————————–111061030216033
Content-Disposition: form-data; name=”resumableCurrentChunkSize”

1048576
—————————–111061030216033
Content-Disposition: form-data; name=”resumableTotalSize”

171309601
—————————–111061030216033
Content-Disposition: form-data; name=”resumableType”

—————————–111061030216033
Content-Disposition: form-data; name=”resumableIdentifier”

171309601-sample7z
—————————–111061030216033
Content-Disposition: form-data; name=”resumableFilename”

sample.7z
—————————–111061030216033
Content-Disposition: form-data; name=”resumableRelativePath”

sample.7z
—————————–111061030216033
Content-Disposition: form-data; name=”resumableTotalChunks”

163
—————————–111061030216033
Content-Disposition: form-data; name=”file”; filename=”blob”
Content-Type: application/octet-stream

XXXCONTENT
—————————–309022088923579–

转载于:https://www.cnblogs.com/caption/p/3966463.html

[开源应用]利用HTTPHandler+resumableJs+HTML5实现拖拽上传[大]文件相关推荐

  1. html5 上传超大文件,HTML5教程 如何拖拽上传大文件

    本篇教程探讨了HTML5教程 如何拖拽上传大文件,希望阅读本篇文章以后大家有所收获,帮助大家HTML5+CSS3从入门到精通 . < 前言: 大文件传输一直是技术上的一大难点.文件过大时,一些性 ...

  2. php拖拽上传大文件,如何实现文件拖拽上传

    拖拽选择文件 屏蔽默认事件 刚开始的时候,是在网上找了一个例子,这个例子中提到,需要在document上屏蔽和drag相关的所有事件的默认处理方式,代码如下:$(document).on({ drag ...

  3. Nodejs express、html5实现拖拽上传(转载)

    一.前言 文件上传是一 个比较常见的功能,传统的选择方式的上传比较麻烦,需要先点击上传按钮,然后再找到文件的路径,然后上传.给用户体验带来很大问题.html5开始支持拖 拽上传的需要的api.node ...

  4. html5带拖拽上传的图片gallary

    改的别人的程序,不能说原创吧,算半个原创 <!DOCTYPE html> <!-- saved from url=(0066)http://enjoyhtml5.com/hackat ...

  5. JavaScript实现拖拽上传 解析 APK 信息

    点击上方蓝字,关注我们 技术栈 jquery 文件上传:jquery.fileupload,github 文档 apk 文件解析:app-info-parser,github 文档 参考:前端解析ip ...

  6. html ajax打包成app,利用HTML5与ajax完成拖拽上传文件

    前言 基于ajax的异步模式的上传控件,基本功能如下: 拖拽上传(利用HTML5新增特定 拖拽事件 以及 event的dataTransfer属性) 单文件/多文件切换(利用php实现单/多文件上传) ...

  7. dropzonejs中文翻译手册 DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库....

    http://wxb.github.io/dropzonejs.com.zh-CN/dropzonezh-CN/ 由于项目需要,完成一个web的图片拖拽上传,也就顺便学习和了解了一下前端的比较新的技术 ...

  8. html5之多文件拖拽上传预览

    最近对于html5预览功能很是感兴趣,特地拿出来研究一小下,并以一个小项目举例讲解. h5中的input有个type=file 就是文件上传控件,有个属性multiple就是h5新增的支持多选上传文件 ...

  9. 使用jQuery开发一个基于HTML5的漂亮图片拖拽上传web应用

    昨天我们介绍了一款HTML5文件上传的jQuery插件:jQuery HTML5 uploader,今天我们将开发一个简单的叫upload center的图片上传程序,允许用户使用拖拽方式来上传电脑上 ...

最新文章

  1. 用DFS 解决全排列问题的思想详解
  2. 图像生成王者不是GAN?扩散模型最近有点火:靠加入类别条件,效果直达SOTA
  3. jetty 在请求URI里传入非法字符,jetty会断开连接,导致nginx认为该节点不健康
  4. 我与计算机编程的不解之缘(2015.9~2022.1)
  5. 云炬随笔20210714(1)
  6. zookeeper是如何实现数据一致性的?
  7. [pytorch、学习] - 3.9 多重感知机的从零开始实现
  8. C语言srand((unsigned)time(NULL))…
  9. 信息学奥赛一本通 1077:统计满足条件的4位数 | OpenJudge NOI 1.5 26
  10. python如何设置api接口_python如何使用api接口
  11. DOS命令tree的用法
  12. linux容器 mac vlan,【Docker】macvlan网络模式下容器与宿主机互通
  13. 重新定义软件定义安全
  14. SQL中计算字符串的长度函数
  15. 2019软科【世界一流计算机学科排名】公布!
  16. eclipse背景设置绿豆色
  17. error: File: XX 520.13 MB, exceeds 100.00 MB以上大文件导致push失败解决方法
  18. 语文网站第十九周推荐博客
  19. 计算机删除打印记录,怎样消除电脑打印痕迹
  20. golang swagger注解说明

热门文章

  1. 不用GAN、VAE,谷歌发明视频生成的扩散模型,实现新SOTA
  2. 全能型AI!用通用预训练感知模型处理多模态多任务!商汤西交港中文提出:Uni-Perceiver...
  3. WenLan-10亿参数!别只玩GPT,来看看人大中科院联手打造第一个大规模多模态中文预训练模型BriVL...
  4. Scikit-learn 更新至0.24版,这10个新特性你需要了解
  5. Github 上近万星的深度学习模型大全!
  6. 收藏 | 那些机器学习必备知识
  7. 复旦大学邱锡鹏教授《神经网络与深度学习》最新版!
  8. 收藏 | 一文看完吴恩达最新演讲精髓,人工智能部署的三大挑战及解决方案
  9. 谷歌推出量子机器学习框架TFQ-TensorFlow Quantum,一个可训练量子模型的机器学习框架...
  10. 数学建模之图论——图与网络模型(一)(基本概念和最短路问题,附MATLAB源码)