·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> [开源应用]利用HTTPHandler+resumableJs+HTML5实现拖拽上传[大]文件

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

作者:佚名      ASP.NET网站开发编辑:admin      更新时间:2022-07-23

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

前言:

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

本文以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 parameters                var 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 File                if (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 parameters                var 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);            //numbers            if (files.Length != numChunks)                return false;            //files all exisit            var 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];