精华内容
下载资源
问答
  • js实现上传文件夹

    千次阅读 2019-06-10 09:50:26
    一般10M以下的文件上传通过设置Web.Config,再用VS自带的FileUpload控件就可以了,但是如果要上传100M甚至1G的文件就不能这样上传了。我这里分享一下我自己开发的一套大文件上传控件供大家参考 控件功能: 1.文件...

    一般10M以下的文件上传通过设置Web.Config,再用VS自带的FileUpload控件就可以了,但是如果要上传100M甚至1G的文件就不能这样上传了。我这里分享一下我自己开发的一套大文件上传控件供大家参考

    控件功能:

    1. 文件批量上传

    此文件管理器支持文件批量上传。您可以上传30G及以上的大型文件,在上传过程中您不需要担心刷新网页造成的进度丢失问题。也不需要担心浏览器重启或崩溃,电脑重启等极端应用场景造成的进度丢失问题。文件管理器能够自动定时保存文件上传进度。以便为您提供更好的用户体验。

     

    2. 文件夹批量上传

    此文件管理器提供文件夹的批量上传功能。您可以同时上传一个或者多个文件夹,文件管理器会将这些文件夹以及他们的结构信息同时保存在服务器中。您不需要担心浏览器重启或崩溃造成的进度丢失的问题。

     

    3. 文件批量下载

    此文件管理器提供了文件批量下载功能。您现在可以同时下载多个文件,并将他们保存在本地指定的目录中。这一功能为图库应用场景,多资料共享应用场景提供了使用便利。

     

    4. 文件夹批量下载

    此文件管理器提供了文件夹的批量下载功能。您可以同时下载多个文件夹,这些文件夹下载完毕后,他们的层级信息也将会同时在本地保留。

     

    5. 新建目录

    此文件管理器提供了多层级目录管理功能。您现在可以根据需求新建目录。

     

    6. 文件目录重命名。

    7. 树型目录导航

    8. 路径导航

    9. 开源

    此文件管理器是开款开源产品,无论您是个人还是企业都可以获取他的源代码来进行二次开发。我们为ASP.NET,JAVA,PHP等语言提供了示例,您可以同时选择这3种开发语言来进行项目开发。同时我们将提供长期的更新和维护服务,帮助企业节省后期的产品维护成本。

     

    这是前端部分脚本代码:

    //文件上传对象
    
    function FileUploader(fileLoc, mgr)
    
    {
    
        var _this = this;
    
        this.id = fileLoc.id;
    
        this.ui = { msg: null, process: null, percent: null, btn: { del: null, cancel: null,post:null,stop:null }, div: null};
    
        this.isFolder = false; //不是文件夹
    
        this.app = mgr.app;
    
        this.Manager = mgr; //上传管理器指针
    
        this.event = mgr.event;
    
        this.FileListMgr = mgr.FileListMgr;//文件列表管理器
    
        this.Config = mgr.Config;
    
        this.fields = jQuery.extend({}, mgr.Config.Fields, fileLoc.fields);//每一个对象自带一个fields幅本
    
        this.State = this.Config.state.None;
    
        this.uid = this.fields.uid;
    
        this.fileSvr = {
    
              pid: ""
    
            , id: ""
    
            , pidRoot: ""
    
            , f_fdTask: false
    
            , f_fdChild: false
    
            , uid: 0
    
            , nameLoc: ""
    
            , nameSvr: ""
    
            , pathLoc: ""
    
            , pathSvr: ""
    
            , pathRel: ""
    
            , md5: ""
    
            , lenLoc: "0"
    
            , sizeLoc: ""
    
            , FilePos: "0"
    
            , lenSvr: "0"
    
            , perSvr: "0%"
    
            , complete: false
    
            , deleted: false
    
        };//json obj,服务器文件信息
    
        this.fileSvr = jQuery.extend(this.fileSvr, fileLoc);
    
    
    
        //准备
    
        this.Ready = function ()
    
        {
    
            this.ui.msg.text("正在上传队列中等待...");
    
            this.State = this.Config.state.Ready;
    
        };
    
    
    
        this.svr_error = function ()
    
        {
    
            alert("服务器返回信息为空,请检查服务器配置");
    
            this.ui.msg.text("向服务器发送MD5信息错误");
    
            this.ui.btn.cancel.text("续传");
    
        };
    
        this.svr_create = function (sv)
    
        {
    
            if (sv.value == null)
    
            {
    
                this.svr_error(); return;
    
            }
    
    
    
            var str = decodeURIComponent(sv.value);//
    
            this.fileSvr = JSON.parse(str);//
    
            //服务器已存在相同文件,且已上传完成
    
            if (this.fileSvr.complete)
    
            {
    
                this.post_complete_quick();
    
            } //服务器文件没有上传完成
    
            else
    
            {
    
                this.ui.process.css("width", this.fileSvr.perSvr);
    
                this.ui.percent.text(this.fileSvr.perSvr);
    
                this.post_file();
    
            }
    
        };
    
        this.svr_update = function () {
    
            if (this.fileSvr.lenSvr == 0) return;
    
            var param = { uid: this.fields["uid"], offset: this.fileSvr.lenSvr, lenSvr: this.fileSvr.lenSvr, perSvr: this.fileSvr.perSvr, id: this.id, time: new Date().getTime() };
    
            $.ajax({
    
                type: "GET"
    
                , dataType: 'jsonp'
    
                , jsonp: "callback" //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
    
                , url: this.Config["UrlProcess"]
    
                , data: param
    
                , success: function (msg) {}
    
                , error: function (req, txt, err) { alert("更新文件进度错误!" + req.responseText); }
    
                , complete: function (req, sta) { req = null; }
    
            });
    
        };
    
        this.post_process = function (json)
    
        {
    
            this.fileSvr.lenSvr = json.lenSvr;//保存上传进度
    
            this.fileSvr.perSvr = json.percent;
    
            this.ui.percent.text("("+json.percent+")");
    
            this.ui.process.css("width", json.percent);
    
            var str = json.lenPost + " " + json.speed + " " + json.time;
    
            this.ui.msg.text(str);
    
        };
    
        this.post_complete = function (json)
    
        {
    
            this.fileSvr.perSvr = "100%";
    
            this.fileSvr.complete = true;
    
            $.each(this.ui.btn, function (i, n)
    
            {
    
                n.hide();
    
            });
    
            this.ui.process.css("width", "100%");
    
            this.ui.percent.text("(100%)");
    
            this.ui.msg.text("上传完成");
    
            this.Manager.arrFilesComplete.push(this);
    
            this.State = this.Config.state.Complete;
    
            //从上传列表中删除
    
            this.Manager.RemoveQueuePost(this.fileSvr.id);
    
            //从未上传列表中删除
    
            this.Manager.RemoveQueueWait(this.fileSvr.id);
    
    
    
            var param = { md5: this.fileSvr.md5, uid: this.uid, id: this.fileSvr.id, time: new Date().getTime() };
    
    
    
            $.ajax({
    
                type: "GET"
    
                 , dataType: 'jsonp'
    
                 , jsonp: "callback" //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
    
                 , url: _this.Config["UrlComplete"]
    
                 , data: param
    
                 , success: function (msg)
    
                 {
    
                     _this.event.fileComplete(_this);//触发事件
    
                     _this.FileListMgr.UploadComplete(_this.fileSvr);//添加到服务器文件列表
    
                     _this.post_next();
    
                 }
    
                 , error: function (req, txt, err) { alert("文件-向服务器发送Complete信息错误!" + req.responseText); }
    
                 , complete: function (req, sta) { req = null; }
    
            });
    
        };
    
        this.post_complete_quick = function ()
    
        {
    
            this.fileSvr.perSvr = "100%";
    
            this.fileSvr.complete = true;
    
            this.ui.btn.stop.hide();
    
            this.ui.process.css("width", "100%");
    
            this.ui.percent.text("(100%)");
    
            this.ui.msg.text("服务器存在相同文件,快速上传成功。");
    
            this.Manager.arrFilesComplete.push(this);
    
            this.State = this.Config.state.Complete;
    
            //从上传列表中删除
    
            this.Manager.RemoveQueuePost(this.fileSvr.id);
    
            //从未上传列表中删除
    
            this.Manager.RemoveQueueWait(this.fileSvr.id);
    
            //添加到文件列表
    
            this.FileListMgr.UploadComplete(this.fileSvr);
    
            this.post_next();
    
            this.event.fileComplete(this);//触发事件
    
        };
    
        this.post_stoped = function (json)
    
        {
    
            this.ui.btn.post.show();
    
            this.ui.btn.del.show();
    
            this.ui.btn.cancel.hide();
    
            this.ui.btn.stop.hide();
    
            this.ui.msg.text("传输已停止....");
    
    
    
            if (this.Config.state.Ready == this.State)
    
            {
    
                this.Manager.RemoveQueue(this.fileSvr.id);
    
                this.post_next();
    
                return;
    
            }
    
            this.State = this.Config.state.Stop;
    
            //从上传列表中删除
    
            this.Manager.RemoveQueuePost(this.fileSvr.id);
    
            this.Manager.AppendQueueWait(this.fileSvr.id);//添加到未上传列表
    
            //传输下一个
    
            this.post_next();
    
        };
    
        this.post_error = function (json)
    
        {
    
            this.svr_update();
    
            this.ui.msg.text(this.Config.errCode[json.value]);
    
            this.ui.btn.stop.hide();
    
            this.ui.btn.post.show();
    
            this.ui.btn.del.show();
    
    
    
            this.State = this.Config.state.Error;
    
            //从上传列表中删除
    
            this.Manager.RemoveQueuePost(this.fileSvr.id);
    
            //添加到未上传列表
    
            this.Manager.AppendQueueWait(this.fileSvr.id);
    
            this.post_next();
    
        };
    
        this.md5_process = function (json)
    
        {
    
            var msg = "正在扫描本地文件,已完成:" + json.percent;
    
            this.ui.msg.text(msg);
    
        };
    
        this.md5_complete = function (json)
    
        {
    
            this.fileSvr.md5 = json.md5;
    
            this.ui.msg.text("MD5计算完毕,开始连接服务器...");
    
            this.event.md5Complete(this, json.md5);//biz event
    
    
    
            var loc_path = encodeURIComponent(this.fileSvr.pathLoc);
    
            var loc_len = this.fileSvr.lenLoc;
    
            var loc_size = this.fileSvr.sizeLoc;
    
            var param = jQuery.extend({}, this.fields, { md5: json.md5, id: this.fileSvr.id, lenLoc: loc_len, sizeLoc: loc_size, pathLoc: loc_path, time: new Date().getTime() });
    
    
    
            $.ajax({
    
                type: "GET"
    
                , dataType: 'jsonp'
    
                , jsonp: "callback" //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
    
                , url: this.Config["UrlCreate"]
    
                , data: param
    
                , success: function (sv)
    
                {
    
                    _this.svr_create(sv);
    
                }
    
                , error: function (req, txt, err)
    
                {
    
                    alert("向服务器发送MD5信息错误!" + req.responseText);
    
                    _this.ui.msg.text("向服务器发送MD5信息错误");
    
                    _this.ui.btn.del.text("续传");
    
                }
    
                , complete: function (req, sta) { req = null; }
    
            });
    
        };
    
        this.md5_error = function (json)
    
        {
    
            this.ui.msg.text(this.Config.errCode[json.value]);
    
            //文件大小超过限制,文件大小为0
    
            if ("4" == json.value
    
                 || "5" == json.value)
    
            {
    
            this.ui.btn.stop.hide();
    
            this.ui.btn.cancel.show();
    
            }
    
            else
    
            {           
    
                this.ui.btn.post.show();
    
                this.ui.btn.stop.hide();
    
            }
    
            this.State = this.Config.state.Error;
    
            //从上传列表中删除
    
            this.Manager.RemoveQueuePost(this.fileSvr.id);
    
            //添加到未上传列表
    
            this.Manager.AppendQueueWait(this.fileSvr.id);
    
    
    
            this.post_next();
    
        };
    
        this.post_next = function ()
    
        {
    
            var obj = this;
    
            setTimeout(function () { obj.Manager.PostNext(); }, 500);
    
        };
    
        this.post = function ()
    
        {
    
            this.Manager.AppendQueuePost(this.fileSvr.id);
    
            this.Manager.RemoveQueueWait(this.fileSvr.id);
    
            if (this.fileSvr.md5.length > 0)
    
            {
    
                this.post_file();
    
            }
    
            else
    
            {
    
                this.check_file();
    
            }
    
        };
    
        this.post_file = function ()
    
        {
    
            this.ui.btn.cancel.hide();
    
            this.ui.btn.stop.show();
    
            this.State = this.Config.state.Posting;//
    
            this.app.postFile({ id: this.fileSvr.id, pathLoc: this.fileSvr.pathLoc, pathSvr:this.fileSvr.pathSvr,lenSvr: this.fileSvr.lenSvr, fields: this.fields });
    
        };
    
        this.check_file = function ()
    
        {
    
            //this.ui.btn.cancel.text("停止").show();
    
            this.ui.btn.stop.show();
    
            this.ui.btn.cancel.hide();
    
            this.State = this.Config.state.MD5Working;
    
            this.app.checkFile({ id: this.fileSvr.id, pathLoc: this.fileSvr.pathLoc });
    
        };
    
        this.stop = function ()
    
        {
    
            this.ui.btn.del.hide();
    
            this.ui.btn.cancel.hide();
    
            this.ui.btn.stop.hide();
    
            this.ui.btn.post.hide();
    
            this.svr_update();
    
            this.app.stopFile({ id: this.fileSvr.id });       
    
        };
    
        //手动停止,一般在StopAll中调用
    
        this.stop_manual = function ()
    
        {
    
            if (this.Config.state.Posting == this.State)
    
            {
    
                this.svr_update();
    
            this.ui.btn.post.show();
    
            this.ui.btn.stop.hide();
    
            this.ui.btn.cancel.hide();
    
                this.ui.msg.text("传输已停止....");
    
                this.app.stopFile({ id: this.fileSvr.id ,tip:false});
    
                this.State = this.Config.state.Stop;
    
            }
    
        };
    
    
    
        //删除,一般在用户点击"删除"按钮时调用
    
        this.remove = function ()
    
        {
    
            this.Manager.del_file(this.fileSvr.id);
    
            this.app.delFile(this.fileSvr);
    
            this.ui.div.remove();
    
        };
    
    }

    这是后台文件块处理代码和截图:

    文件上传完毕,f_complete.

    文件初始化,f_create

    文件块处理,f_post

    文件夹上传完毕,fd_complete

    文件夹初始化,fd_create

    using Newtonsoft.Json;
    
    using Newtonsoft.Json.Linq;
    
    using System;
    
    using System.Web;
    
    using up6.db.biz;
    
    using up6.db.utils;
    
    
    
    namespace up6.db
    
    {
    
        public partial class f_post : System.Web.UI.Page
    
        {
    
            bool safe_check(params string[] ps)
    
            {
    
                foreach (var v in ps)
    
                {
    
                    System.Diagnostics.Debug.Write("参数值:");
    
                    System.Diagnostics.Debug.WriteLine(v);
    
                    if (string.IsNullOrEmpty(v)) return false;
    
                }
    
                foreach (string key in Request.Headers.Keys)
    
                {
    
                    var vs = Request.Headers.GetValues(key);
    
                    //XDebug.Output(key + " "+String.Join(",", vs));
    
                }
    
                return true;
    
            }
    
    
    
            /// <summary>
    
            /// 只负责拼接文件块。将接收的文件块数据写入到文件中。
    
            /// 更新记录:
    
            ///       2012-04-12 更新文件大小变量类型,增加对2G以上文件的支持。
    
            ///       2012-04-18 取消更新文件上传进度信息逻辑。
    
            ///       2012-10-30 增加更新文件进度功能。
    
            ///       2015-03-19 文件路径由客户端提供,此页面不再查询文件在服务端的路径。减少一次数据库访问操作。
    
            ///     2016-03-31 增加文件夹信息字段
    
            ///     2017-07-11 优化参数检查逻辑
    
            /// </summary>
    
            /// <param name="sender"></param>
    
            /// <param name="e"></param>
    
            protected void Page_Load(object sender, EventArgs e)
    
            {
    
                string uid          = Request.Headers["uid"];
    
                string f_id         = Request.Headers["id"];
    
                string lenSvr       = Request.Headers["lenSvr"];//已传大小
    
                string lenLoc       = Request.Headers["lenLoc"];//本地文件大小
    
                string blockOffset  = Request.Headers["blockOffset"];
    
                string blockSize    = Request.Headers["blockSize"];//当前块大小
    
                string blockIndex   = Request.Headers["blockIndex"];//当前块索引,基于1
    
                string blockMd5     = Request.Headers["blockMd5"];//块MD5
    
                string complete     = Request.Headers["complete"];//true/false
    
                string pathSvr      = Request.Form["pathSvr"];//
    
                pathSvr             = HttpUtility.UrlDecode(pathSvr);
    
    
    
                if( !this.safe_check(lenLoc,uid,f_id,blockOffset,pathSvr)) return;
    
    
    
                //有文件块数据
    
                if (Request.Files.Count > 0)
    
                {
    
                    bool verify = false;
    
                    string msg = string.Empty;
    
                    string md5Svr = string.Empty;
    
                    HttpPostedFile file = Request.Files.Get(0);//文件块
    
    
    
                    //计算文件块MD5
    
                    if (!string.IsNullOrEmpty(blockMd5))
    
                    {
    
                        md5Svr = Md5Tool.calc(file.InputStream);
    
                    }
    
    
    
                    //文件块大小验证
    
                    verify = int.Parse(blockSize) == file.InputStream.Length;
    
                    if (!verify)
    
                    {
    
                        msg = "block size error sizeSvr:"+file.InputStream.Length + " sizeLoc:"+blockSize;
    
                    }
    
    
    
                    //块MD5验证
    
                    if ( verify && !string.IsNullOrEmpty(blockMd5) )
    
                    {
    
                        verify = md5Svr == blockMd5;
    
                        if(!verify) msg = "block md5 error";
    
                    }
    
    
    
                    if (verify)
    
                    {
    
                        //2.0保存文件块数据
    
                        FileBlockWriter res = new FileBlockWriter();
    
                        res.make(pathSvr, Convert.ToInt64(lenLoc));
    
                        res.write(pathSvr, Convert.ToInt64(blockOffset), ref file);
    
                        up6_biz_event.file_post_block(f_id,Convert.ToInt32(blockIndex));
    
    
    
                        //生成信息
    
                        JObject o = new JObject();
    
                        o["msg"] = "ok";
    
                        o["md5"] = md5Svr;//文件块MD5
    
                        o["offset"] = blockOffset;//偏移
    
                        msg = JsonConvert.SerializeObject(o);
    
                    }
    
                    Response.Write(msg);
    
                }
    
            }
    
        }
    
    }

    新建文件夹

    点击新建文件夹按钮,弹出此窗口,填写新建文件夹名称后点击确定

    页面左上角出现刚刚新建的文件夹名称

    粘贴上传

    复制文件夹、文件或图片

    在页面中选择好相应的上传目录,点击粘贴上传按钮,数据即可快速开始上传

     

    文件和文件夹批量上传上传功能,在新建文件夹目录内上传文件,选择多个文件或文件夹上传

    如果上传的是文件夹,那么左侧的文件夹内会自动添加一个子文件夹,与上传的文件夹相符并可以展开查看文件夹内文件

    在哪个目录下上传文件,文件就会存储在哪个目录下

     

    点击根目录按钮可以返回根目录

    当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件。另外分片传输能够更加实时的跟踪上传进度。

     

    上传成功后打开我们的存储文件夹查看,发现自动生成了几个文件夹,打开文件夹确认上传文件成功

     

    点击文件夹后的重命名按钮

    修改文件名后点击确定

    页面左侧文件夹与页面中间的文件夹名称同时改变

     

    点击删除按钮

    点击确定后,页面中的文件消失

     

    文件及文件夹批量下载

    这是下载所需的脚本截图和部分代码:

    using System;
    
    using System.IO;
    
    using System.Web;
    
    
    
    namespace up6.down2.db
    
    {
    
        public partial class f_down : System.Web.UI.Page
    
        {
    
            bool check_params(params string[] vs)
    
            {
    
                foreach(string v in vs)
    
                {
    
                    if (String.IsNullOrEmpty(v)) return false;
    
                }
    
                return true;
    
            }
    
    
    
            protected void Page_Load(object sender, EventArgs e)
    
            {
    
                string id           = Request.Headers["id"];//文件id
    
                string blockIndex   = Request.Headers["blockIndex"];//基于1
    
                string blockOffset  = Request.Headers["blockOffset"];//块偏移,相对于整个文件
    
                string blockSize    = Request.Headers["blockSize"];//块大小(当前需要下载的)
    
                string pathSvr      = Request.Headers["pathSvr"];//文件在服务器的位置
    
                pathSvr             = HttpUtility.UrlDecode(pathSvr);
    
    
    
                if ( !this.check_params(id,blockIndex,blockOffset,pathSvr))
    
                {
    
                    Response.StatusCode = 500;
    
                    return;
    
                }
    
    
    
                Stream iStream = null;
    
                try
    
                {
    
                    // Open the file.
    
                    iStream = new FileStream(pathSvr, FileMode.Open, FileAccess.Read, FileShare.Read);
    
                    iStream.Seek(long.Parse(blockOffset),SeekOrigin.Begin);//定位
    
    
    
                    // Total bytes to read:
    
                    long dataToRead = long.Parse(blockSize);
    
    
    
                    Response.ContentType = "application/octet-stream";
    
                    Response.AddHeader("Content-Length", blockSize );
    
    
    
                    int buf_size = Math.Min(1048576, int.Parse(blockSize));
    
                    byte[] buffer = new Byte[ buf_size];
    
                    int length;
    
                    while (dataToRead > 0)
    
                    {
    
                        // Verify that the client is connected.
    
                        if (Response.IsClientConnected)
    
                        {
    
                            // Read the data in buffer.
    
                            length = iStream.Read(buffer, 0, buf_size);
    
                            dataToRead -= length;
    
    
    
                            // Write the data to the current output stream.
    
                            Response.OutputStream.Write(buffer, 0, length);
    
    
    
                            // Flush the data to the HTML output.
    
                            Response.Flush();
    
                        }
    
                        else
    
                        {
    
                            //prevent infinite loop if user disconnects
    
                            dataToRead = -1;
    
                        }
    
                    }
    
                }
    
                catch (Exception ex)
    
                {
    
                    Response.StatusCode = 500;
    
                    // Trap the error, if any.
    
                    Response.Write("Error : " + ex.Message);
    
                }
    
                finally
    
                {
    
                    if (iStream != null)
    
                    {
    
                        //Close the file.
    
                        iStream.Close();
    
                    }
    
                }
    
    
    
            }
    
        }
    
    }

    选择上传后的文件夹内的子目录文件或文件夹下载

     

    然后点击下载按钮,设置下载目录文件夹

    设置完成后继续点击下载按钮,页面的右下角出现了下载面板,你选择的文件已出现在目录中,然后点击全部下载,或者单个点击继续,自动加载未上传完的任务。在刷新浏览器或重启电脑后任然可以自动加载未完成的任务

     

    下载完成后打开我们设置的下载目录文件夹,发现需下载的文件或文件夹确认已下载成功,经确认文件夹内的内容与下载文件夹内容一致

     

    数据库记录

    控件包下载:
    cab(x86):http://t.cn/Ai9pmG8S

    cab(x64):http://t.cn/Ai9pm04B

    xpi:http://t.cn/Ai9pubUc

    crx:http://t.cn/Ai9pmrcy

    exe:http://t.cn/Ai9puobe

     

    示例下载:

    asp.net:http://t.cn/Ai9pue4A

    jsp-eclipse:http://t.cn/Ai9p3LSx

    jsp-myeclipse:http://t.cn/Ai9p3IdC

    php: http://t.cn/Ai9p3CKQ

     

    在线教程:
    asp.net-文件管理器教程:http://j.mp/2MLoQWf

    jsp-文件管理器教程:http://j.mp/2WJ2Y1m

    php-文件管理器教程:http://j.mp/2MudPs3

    展开全文
  • 上传文件大家都写过,直接上传目录我也是第一次写,经过一番百度编程,结合项目需求,变为以下代码,仅供参考。 前台html整页代码 <!DOCTYPE html> <...上传文件夹</title> &...

    前台html整页代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>上传文件夹</title>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
    </head>
    <body>
    <form action="/file/upload" enctype="multipart/form-data" method="post">
        <input type='file' webkitdirectory >
        <button id="upload-btn" type="button">upload</button>
    </form>
    </body>
    
    <script>
        $(function () {
            var files = [];
            // 操作dom获取input的数据,多个input的话,用id获取
            $(document).ready(function(){
                $("input").change(function(){
                    files = this.files;
                });
            });
            // 绑定点击事件,ajax请求
            $("#upload-btn").click(function () {
                var formData = new FormData();
                for (var i = 0; i < files.length; i++) {
                    // "file"是后台接口的参数名
                    formData.append("file", files[i]);
                }
                $.ajax({
                    url : "换成后台接口路径",
                    type : 'POST',
                    data : formData,
                    contentType : false,
                    processData : false,
                    cache : false,
                    success : function(data) {
                        console.log("成功!");
                    }
                });
            })
        })
    </script>
    </html>

    java接口完整代码

    @ApiOperation(value = "上传文件夹")
    @RequestMapping(value = "/wenjianjia", headers = "content-type=multipart/*", method = RequestMethod.POST)
    public Result<Object> upload(@RequestParam("file") MultipartFile[] file) {
        for (MultipartFile mf : file) {
            File file1;
            String name = "";
            try {
                //转换成这个对象,然后我们需要通过里面的FileItem来获得相对路径
                CommonsMultipartFile f2 = (CommonsMultipartFile) mf;
                name = f2.getFileItem().getName();
                file1 = new File(System.getProperty("user.dir") + "/test/" + name);
                file1.mkdirs();
                file1.createNewFile();
                mf.transferTo(file1);
            } catch (Exception e) {
                e.printStackTrace();
                return new ResultUtil<Object>().setErrorMsg("上传文件夹失败," + e.getMessage());
            }
        }
        return new ResultUtil<Object>().setSuccessMsg("上传文件夹成功");
    }

    代码说明:

    • Result是我封装的交互类,你们要换成自己的出参。
    • System.getProperty("user.dir")是java获取项目根目录绝对路径的方法。
    • CommonsMultipartFile需要pom.xml导入依赖。
    • <dependency>
      	<groupId>commons-fileupload</groupId>
      	<artifactId>commons-fileupload</artifactId>
      	<version>1.3.1</version>
      </dependency>
    • Application启动类:
      • 须添加以下配置,否则,MultipartFile转CommonsMultipartFile会报错。
      • 允许自动加载,@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
      @SpringBootApplication
      @EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
      public class ServerApplication {
      
          public static void main(String[] args) {
              SpringApplication.run(ServerApplication.class, args);
          }
      
          @Bean(name = "multipartResolver")
          public MultipartResolver multipartResolver(){
              CommonsMultipartResolver resolver = new CommonsMultipartResolver();
              resolver.setDefaultEncoding("UTF-8");
              resolver.setResolveLazily(true);
              //resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常
              resolver.setMaxInMemorySize(20971520);// 根据需求更换大小
              resolver.setMaxUploadSize(104857600);// 根据需求更换大小
              return resolver;
          }
      }

     

    测试

     

     

    展开全文
  • JavaScript实现选择文件夹

    热门讨论 2010-02-09 00:21:47
    js实现选择文件夹js实现选择文件夹js实现选择文件夹js实现选择文件夹
  •  最近做了一个项目,需要实现上传文件夹和批量上传文件的功能,发现input标签是可以实现这两个功能的,但是上传文件夹功能还不能兼容全部的浏览器,目前只有谷歌浏览器和Microsoft Edge可以实现上传文件夹的功能,...

     最近做了一个项目,需要实现上传文件夹和批量上传文件的功能,发现input标签是可以实现这两个功能的,但是上传文件夹功能还不能兼容全部的浏览器,目前只有谷歌浏览器和Microsoft Edge可以实现上传文件夹的功能,其他浏览器会直接变成上传文件。

     实现上传文件夹的功能只需要在input标签中加入 webkitdirectory='true'即可,而 multiple='true' 表示可以上传多个文件,注意,这里指定是上传多个文件,目前的文件夹暂时不支持同时上传多个。下面举个例子:

    1、上传文件夹
    <input
          ref="input"
          webkitdirectory
          type="file"
          @change="handleChange"
          @click="handelClick"
        >
    
    效果图:

    在这里插入图片描述

    2、上传多个文件,需不需要同时上传多个可根据需求设置,这里的例子是可同时上传多个文件
    <input
          ref="input"
          :multiple="true"
          type="file"
          @change="handleChange"
          @click="handelClick"
        >
    
    效果图:

    在这里插入图片描述
    希望上述可以帮助到大家!

    展开全文
  • java实现上传文件夹

    2019-08-23 15:44:05
    我们平时经常做的是上传文件,上传文件夹上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小限制,post...

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。

    首先我们需要了解的是上传文件三要素:

    1.表单提交方式:post (get方式提交有大小限制,post没有)

    2.表单的enctype属性:必须设置为multipart/form-data.

    3.表单必须有文件上传项:file,且文件项需要给定name值

    上传文件夹需要增加一个属性webkitdirectory,像这样:

    <input id="fileFolder" name="fileFolder" type="file"  webkitdirectory>

    不过webkitdirectory属性有个问题,只能支持高版本的chrome,不能支持低版本的IE,如ie6,ie7,ie8,不能做到全浏览器适配,运行环境比较单一。

    js中可以判断文件夹中文件数量及文件夹大小是否符合要求,不符合要求不能向后台提交:

    前台HTML模板

    this.GetHtmlFiles = function()

    {

         var acx = "";

         acx += '<div class="file-item" id="tmpFile" name="fileItem">\

                    <div class="img-box"><img name="file" src="js/file.png"/></div>\

                       <div class="area-l">\

                           <div class="file-head">\

                                <div name="fileName" class="name">HttpUploader程序开发.pdf</div>\

                                <div name="percent" class="percent">(35%)</div>\

                                <div name="fileSize" class="size" child="1">1000.23MB</div>\

                        </div>\

                           <div class="process-border"><div name="process" class="process"></div></div>\

                           <div name="msg" class="msg top-space">15.3MB 20KB/S 10:02:00</div>\

                       </div>\

                       <div class="area-r">\

                        <span class="btn-box" name="cancel" title="取消"><img name="stop" src="js/stop.png"/><div>取消</div></span>\

                        <span class="btn-box hide" name="post" title="继续"><img name="post" src="js/post.png"/><div>继续</div></span>\

                           <span class="btn-box hide" name="stop" title="停止"><img name="stop" src="js/stop.png"/><div>停止</div></span>\

                           <span class="btn-box hide" name="del" title="删除"><img name="del" src="js/del.png"/><div>删除</div></span>\

                       </div>';

         acx += '</div>';

         //文件夹模板

         acx += '<div class="file-item" name="folderItem">\

                       <div class="img-box"><img name="folder" src="js/folder.png"/></div>\

                       <div class="area-l">\

                           <div class="file-head">\

                                <div name="fileName" class="name">HttpUploader程序开发.pdf</div>\

                                <div name="percent" class="percent">(35%)</div>\

                                <div name="fileSize" class="size" child="1">1000.23MB</div>\

                        </div>\

                           <div class="process-border top-space"><div name="process" class="process"></div></div>\

                           <div name="msg" class="msg top-space">15.3MB 20KB/S 10:02:00</div>\

                       </div>\

                       <div class="area-r">\

                        <span class="btn-box" name="cancel" title="取消"><img name="stop" src="js/stop.png"/><div>取消</div></span>\

                        <span class="btn-box hide" name="post" title="继续"><img name="post" src="js/post.png"/><div>继续</div></span>\

                           <span class="btn-box hide" name="stop" title="停止"><img name="stop" src="js/stop.png"/><div>停止</div></span>\

                           <span class="btn-box hide" name="del" title="删除"><img name="del" src="js/del.png"/><div>删除</div></span>\

                       </div>';

         acx += '</div>';

         //上传列表

         acx += '<div class="files-panel" name="post_panel">\

                       <div name="post_head" class="toolbar">\

                           <span class="btn" name="btnAddFiles">选择多个文件</span>\

                           <span class="btn" name="btnAddFolder">选择文件夹</span>\

                           <span class="btn" name="btnPasteFile">粘贴文件和目录</span>\

                           <span class="btn" name="btnSetup">安装控件</span>\

                       </div>\

                       <div class="content" name="post_content">\

                           <div name="post_body" class="file-post-view"></div>\

                       </div>\

                       <div class="footer" name="post_footer">\

                           <span class="btn-footer" name="btnClear">清除已完成文件</span>\

                       </div>\

                  </div>';

         return acx;

    };

    选择文件,选择文件夹,粘贴文件和文件夹的逻辑

    this.open_files = function (json)

    {

         for (var i = 0, l = json.files.length; i < l; ++i)

        {

             this.addFileLoc(json.files[i]);

         }

         setTimeout(function () { _this.PostFirst(); },500);

    };

    this.open_folders = function (json)

    {

        for (var i = 0, l = json.folders.length; i < l; ++i) {

            this.addFolderLoc(json.folders[i]);

        }

         setTimeout(function () { _this.PostFirst(); }, 500);

    };

    this.paste_files = function (json)

    {

         for (var i = 0, l = json.files.length; i < l; ++i)

         {

             this.addFileLoc(json.files[i]);

         }

    };

    后台在接收文件夹时不同之处在需要用MultipartHttpServletRequest

    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    FileItemFactory factory = new DiskFileItemFactory();  

    ServletFileUpload upload = new ServletFileUpload(factory);

    List files = null;

    try

    {

         files = upload.parseRequest(request);

    }

    catch (FileUploadException e)

    {// 解析文件数据错误 

        out.println("read file data error:" + e.toString());

        return;

      

    }

     

    FileItem rangeFile = null;

    // 得到所有上传的文件

    Iterator fileItr = files.iterator();

    // 循环处理所有文件

    while (fileItr.hasNext())

    {

         // 得到当前文件

         rangeFile = (FileItem) fileItr.next();

         if(StringUtils.equals( rangeFile.getFieldName(),"pathSvr"))

         {

             pathSvr = rangeFile.getString();

             pathSvr = PathTool.url_decode(pathSvr);

         }

    }

     

    server端的包和类

     

    文件块处页面,验证代码部分

    boolean verify = false;

    String msg = "";

    String md5Svr = "";

    long blockSizeSvr = rangeFile.getSize();

    if(!StringUtils.isBlank(blockMd5))

    {

         md5Svr = Md5Tool.fileToMD5(rangeFile.getInputStream());

    }

     

    verify = Integer.parseInt(blockSize) == blockSizeSvr;

    if(!verify)

    {

         msg = "block size error sizeSvr:" + blockSizeSvr + "sizeLoc:" + blockSize;

    }

     

    if(verify && !StringUtils.isBlank(blockMd5))

    {

         verify = md5Svr.equals(blockMd5);

         if(!verify) msg = "block md5 error";

    }

     

    if(verify)

    {

         //保存文件块数据

         FileBlockWriter res = new FileBlockWriter();

         //仅第一块创建

         if( Integer.parseInt(blockIndex)==1) res.CreateFile(pathSvr,Long.parseLong(lenLoc));

         res.write( Long.parseLong(blockOffset),pathSvr,rangeFile);

         up6_biz_event.file_post_block(id,Integer.parseInt(blockIndex));

        

         JSONObject o = new JSONObject();

         o.put("msg", "ok");

         o.put("md5", md5Svr); 

         o.put("offset", blockOffset);//基于文件的块偏移位置

         msg = o.toString();

    }

    rangeFile.delete();

    out.write(msg);

     

    生成文件名称的逻辑

    publicString genFile(int uid, String md5,String nameLoc) throws IOException

    {

         SimpleDateFormat fmtDD = newSimpleDateFormat("dd");

         SimpleDateFormat fmtMM = newSimpleDateFormat("MM");

         SimpleDateFormat fmtYY = newSimpleDateFormat("yyyy");

        

         Date date = newDate();

         String strDD = fmtDD.format(date);

         String strMM = fmtMM.format(date);

         String strYY = fmtYY.format(date);

        

         String path = this.getRoot() + "/";

         path = path.concat(strYY);

         path = path.concat("/");

         path = path.concat(strMM);

         path = path.concat("/");

         path = path.concat(strDD);

         path = path.concat("/");

         path = path.concat(md5);

         path = path.concat(".");

         path = path.concat(PathTool.getExtention(nameLoc));

            

        

         File fl = newFile(path);

        

         return fl.getCanonicalPath();//

    }

     

    以下是service层做的处理:

    整体模块划分如下:

    其中数据类实体逻辑处理如下

    publicclassFileInf {

     

         public FileInf(){}

         publicStringid="";

         publicStringpid="";

        publicStringpidRoot="";   

         /**  * 表示当前项是否是一个文件夹项。    */

         publicbooleanfdTask=false;        

         //   /// 是否是文件夹中的子文件  /// </summary>

         publicbooleanfdChild=false;

         /**  * 用户ID。与第三方系统整合使用。    */

         publicintuid=0;

         /**  * 文件在本地电脑中的名称   */

         publicStringnameLoc="";

         /**  * 文件在服务器中的名称。   */

         publicStringnameSvr="";

         /**  * 文件在本地电脑中的完整路径。示例:D:\Soft\QQ2012.exe */

         publicStringpathLoc="";  

         /**  * 文件在服务器中的完整路径。示例:F:\\ftp\\uer\\md5.exe     */

         publicStringpathSvr="";

         /**  * 文件在服务器中的相对路径。示例:/www/web/upload/md5.exe   */

         publicStringpathRel="";

         /**  * 文件MD5    */

         publicStringmd5="";

         /**  * 数字化的文件长度。以字节为单位,示例:120125    */

         publiclonglenLoc=0;

         /**  * 格式化的文件尺寸。示例:10.03MB   */

         publicStringsizeLoc="";

         /**  * 文件续传位置。  */

         publiclongoffset=0;

         /**  * 已上传大小。以字节为单位 */

         publiclonglenSvr=0;

         /**  * 已上传百分比。示例:10%  */

         publicStringperSvr="0%";

         publicbooleancomplete=false;

         publicDatePostedTime = newDate();

         publicbooleandeleted=false;

         /**  * 是否已经扫描完毕,提供给大型文件夹使用,大型文件夹上传完毕后开始扫描。  */

         publicbooleanscaned=false;

    }

    后台数据库中的逻辑基本上都用到了上面的实体类

    文件数据表操作类如下

    加载所有未完成的文件列表

    publicString GetAllUnComplete(int f_uid)

    {

         StringBuilder sb = newStringBuilder();

         sb.append("select ");

         sb.append(" f_id");

         sb.append(",f_fdTask");    

         sb.append(",f_nameLoc");

         sb.append(",f_pathLoc");

         sb.append(",f_md5");

         sb.append(",f_lenLoc");

         sb.append(",f_sizeLoc");

         sb.append(",f_pos");

         sb.append(",f_lenSvr");

         sb.append(",f_perSvr");

         sb.append(",f_complete");

         sb.append(",f_pathSvr");//fix(2015-03-16):修复无法续传文件的问题。

         sb.append(" from up6_files ");//change(2015-03-18):联合查询文件夹数据

         sb.append(" where f_uid=? and f_deleted=0 and f_fdChild=0 and f_complete=0 and f_scan=0");//fix(2015-03-18):只加载未完成列表

     

         ArrayList<FileInf> files = newArrayList<FileInf>();

         DbHelper db = newDbHelper();

         PreparedStatement cmd = db.GetCommand(sb.toString());

         try {

             cmd.setInt(1, f_uid);

             ResultSet r = db.ExecuteDataSet(cmd);

             while(r.next())

             {

                  FileInf f          = newFileInf();

                  f.uid              = f_uid;

                  f.id              = r.getString(1);

                  f.fdTask     = r.getBoolean(2);              

                  f.nameLoc         = r.getString(3);

                  f.pathLoc         = r.getString(4);

                  f.md5             = r.getString(5);

                  f.lenLoc     = r.getLong(6);

                  f.sizeLoc         = r.getString(7);

                  f.offset     = r.getLong(8);

                  f.lenSvr     = r.getLong(9);

                  f.perSvr     = r.getString(10);

                  f.complete        = r.getBoolean(11);

                  f.pathSvr     = r.getString(12);//fix(2015-03-19):修复无法续传文件的问题。

                  files.add(f);

                 

             }

             r.close();

             cmd.getConnection().close();

             cmd.close();

         } catch (SQLException e) {

             // TODO Auto-generated catch block

             e.printStackTrace();

         }

        

         if(files.size() < 1) returnnull;

        

         Gson g = newGson();

        return g.toJson( files);//bug:arrFiles为空时,此行代码有异常

    }

    实现后的整体效果如下

    文件夹上传完后的效果

    服务器保存的文件夹数据,而且层级结构与本地客户端是一致的。这在OA系统中,或者网盘系统中使用时是非常有用的

    后端代码逻辑大部分是相同的,目前能够支持MySQL,Oracle,SQL。在使用前需要配置一下数据库,可以参考我写的这篇文章:http://blog.ncmem.com/wordpress/2019/08/11/java%E5%AE%9E%E7%8E%B0%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6%E5%A4%B9/

    展开全文
  • java+实现上传文件夹

    2019-08-23 09:51:36
    我们平时经常做的是上传文件,上传文件夹上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小限制,post...
  • js+上传文件夹

    2019-08-20 09:17:02
    我们平时经常做的是上传文件,上传文件夹上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,ie8,ie9,...
  • js能否上传文件夹

    2019-08-15 18:12:02
    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠。网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹。今天...
  • JS实现文件夹选择.HTML

    热门讨论 2013-07-18 11:44:39
    使用js实现文件夹选择功能,操作方便简单
  • 实现一个效果,上传这个文件夹中的所有的文件,我已经用vue-simple-upload这个插件实现了,但是现在是上传一个文件请求一次,怎么把它一个接口上传多个文件,求解。
  • HTTP协议本身不支持断点上传,需要自己实现。 二、Range 用于请求头中,指定第一个字节的位置和最后一个字节的位置,一般格式: Range:用于客户端到服务端的请求,可以通过改字段指定下载文件的某一段大小...
  • 前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对 Http 协议较模糊,故这次采用渐进的方式来学习文件上传的原理与实践。该博客重在实践。 一. ...
  • js上传文件夹

    2019-06-10 10:07:27
    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠。网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹。今天...
  • js 拖拽上传文件夹

    2021-03-23 16:09:54
    获取拖拽到指定元素上的文件夹中的文件,并需要知道相对地址。 项目地址 https://github.com/156ban/droped-file-and-folder-reader (服务器中运行) 注意 一些方法在mdn上是实验性技术,请在生产中使用它之前仔细...
  • js上传整个文件夹

    千次阅读 2019-08-26 16:57:26
    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠。网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹。今天...
  • 主要介绍了node.js与C语言 实现遍历文件夹下最大的文件,并输出路径,大小的相关资料,需要的朋友可以参考下
  • 项目中有需要实现拖拽文件夹上传功能,虽然可以通过设置input 的webkitdirectory属性实现。但是这种方式的兼容性却不好。如图: webkitdirectory兼容性 博主找遍全网都没有找到合适的解决方案,直到发现下面一篇...
  • 支持文件夹批量上传下载,服务器端保留文件夹层级结构,服务器端文件夹层级结构与本地相同。 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验; 支持文件夹上传文件夹中的文件...
  •  * 以供用户实现对系统文件夹选择的功能  * 文件夹选择对话框起始目录由  * Shell.BrowseForFolder(WINDOW_HANDLE, Message, OPTIONS, strPath)函数  * 的strPath参数设置  * 例如:
  • 1.安装时间处理 及 压缩 模块yarn add...文件保存路径config/config.default.jsconfig.uploadDir = 'app/public/avatar/upload';3.创建tools serviceapp/service/tools.js'use strict';const Service = require('egg...
  • 文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦、缺乏交互、用户体验差。 一、前端代码 英国程序员Remy Sharp总结了这些新的接口,本文在他的基础之上,讨论在前端采用HTML5的API,对...
  • 由于工作中业务需要在界面提供用户上传文件夹的功能,平时上传文件做的还...,但对上传文件夹的支持就没有,h5里提供了webkitdirectory 来实现上传文件夹的功能,但它仅支持Chrome。话不多说,上代码 HTML代码:
  • 下面这个示例便是使用ASP.NET来实现上传文件夹并对文件夹进行压缩以及解压。 ASP.NET页面设计:TextBox和Button按钮。 TextBox中需要自己受到输入文件夹的路径(包含文件夹),通过Button实现选择文件夹的问题还...
  • webkitdirectory 实现文件夹上传

    千次阅读 2019-06-24 09:14:00
    文件夹上传这个功能在web端可能有需求,这里就简单介绍下用法。 目前只有谷歌浏览器还有Microsoft Edge支持按照文件夹进行上传,具体可以看下百度云盘的网页版的上传按钮,在火狐下就支持按照文件进行上传,而在...
  • Only Project JS " : special_names = [ " wwwroot\js " ] else : special_names = [] # local_dir=r'd:\ENZO\Publish\Wxcrm.Admin\bin\release\netcoreapp2.1\centos.7-x64\publish' # remote_dir=r'/...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,012
精华内容 15,604
关键字:

js实现上传文件夹