html大文件传输讨论

需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制。

第一步:

前端修改

由于项目使用的是BJUI前端框架,并没有使用框架本身的文件上传控件,而使用的基于jQuery的Uploadify文件上传组件,在项目使用的jslib项目中找到了BJUI框架集成jQuery Uploadify的部分,这部分代码封装在bjui-all.js文件中,

在bjui-all.js文件中的全局变量定义中有以下部分代码,这就是定义的有关于上传的Uploadify控件的重要变量:

//文件上传对象

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.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.ui.btn.post.click(function () {

_this.ui.btn.post.hide();

_this.ui.btn.del.hide();

_this.ui.btn.cancel.hide();

_this.ui.btn.stop.show();

if (!_this.Manager.IsPostQueueFull()) {

_this.post();

else {

_this.ui.msg.text(“正在上传队列中等待…”);

_this.State = _this.Config.state.Ready;

$.each(_this.ui.btn, function (i, n) { n.hide(); });

_this.ui.btn.del.show();

//添加到队列

_this.Manager.AppendQueue(_this.fileSvr.id);

});

this.ui.btn.stop.click(function () {

_this.stop();

});

this.ui.btn.del.click(function () {

_this.stop();

_this.remove();

});

this.ui.btn.cancel.click(function () {

_this.stop();

_this.remove();

//_this.PostFirst();//

});

this.svr_error = function ()

alert(“服务器返回信息为空,请检查服务器配置”);

this.ui.msg.text(“向服务器发送MD5信息错误”);

//this.ui.btn.cancel.text(“续传”);

this.ui.btn.stop.hide();

this.ui.btn.cancel.show();

this.svr_error_same_name = function () {

this.ui.msg.text(“服务器存在同名文件”);

this.ui.btn.stop.hide();

this.ui.btn.cancel.show();

this.svr_create = function (sv)

if (sv.value == null)

this.Manager.RemoveQueuePost(this.fileSvr.id);

this.svr_error(); return;

if (!sv.ret) {

this.Manager.RemoveQueuePost(this.fileSvr.id);

this.svr_error_same_name(); 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.svr_remove = function ()

var param = { uid: this.fields[“uid”], id: this.fileSvr.id, time: new Date().getTime() };

$.ajax({

type: “GET”

, dataType: ‘jsonp’

, jsonp: “callback” //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名

, url: this.Config[“UrlDel”]

, 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.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.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, this.Config.bizData, { 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)

_this.Manager.RemoveQueuePost(_this.fileSvr.id);

alert(“向服务器发送MD5信息错误!” + req.responseText);

_this.ui.msg.text(“向服务器发送MD5信息错误”);

_this.ui.btn.cancel.show();

_this.ui.btn.stop.hide();

, 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(); }, 300);

this.post = function ()

this.Manager.AppendQueuePost(this.fileSvr.id);

this.Manager.RemoveQueueWait(this.fileSvr.id);

if (this.fileSvr.md5.length > 0 || this.fileSvr.lenSvr > 0)

this.post_file();

else

this.check_file();

this.post_file = function ()

$.each(this.ui.btn, function (i, n) { n.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 ()

$.each(this.ui.btn, function (i, n) { n.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();

if (this.State != this.Config.state.Complete) this.svr_remove();

upload:{uploadLimit:5,fileSizeLimit:31744,removeTimeout:0.8}

以上三个变量代表的含义是:

uploadLimit:表示上传文件个数的限制,5表示文件上传个数限制是5个

fileSizeLimit:表示上传文件大小的限制,31744单位是KB,也就是表示31M

removeTimeout:表示移除文件的时间限制

继续查找使用到这些变量的地方,看到了文件大小超出限制等

了解了BJUI前端框架对于上传大文件的限制,可以这样使用,增大文件上传大小和数量,可以按照如下进行修改,我们在bjui-all.js文件看到uploadLimit属性和fileSizeLimit属性的限制,我们在jsp文件中可以这样进行替换,这里使用的是覆盖原则,重新定义uploadLimit属性和fileSizeLimit属性,覆盖bjui-all.js文件的默认值设置。

bjui-all.js文件的uploadLimit属性和fileSizeLimit属性对应到jsp文件中的属性就应该这样写,data-upload-limit属性和data-file-size-limit属性,只需要在后面改写为data-upload-limit=”800″和data-file-size-limit=”5131264″即可,一定要注意这里的单位是KB,以上数字表示501M。

关于Uploadify控件属性可以参考这篇文章也可以直接看官网文档:

属性名称

默认值

auto

true

设置为true当选择文件后就直接上传了,为false需要点击上传按钮才上传 。

buttonClass

按钮样式

buttonCursor

‘hand’

鼠标指针悬停在按钮上的样子

buttonImage

null

浏览按钮的图片的路径 。

buttonText

‘SELECT FILES’

浏览按钮的文本。

checkExisting

false

文件上传重复性检查程序,检查即将上传的文件在服务器端是否已存在,存在返回1,不存在返回0

debug

false

如果设置为true则表示启用SWFUpload的调试模式

fileObjName

‘Filedata’

文件上传对象的名称,如果命名为’the_files’,PHP程序可以用$_FILES[‘the_files’]来处理上传的文件对象。

fileSizeLimit

上传文件的大小限制 ,如果为整数型则表示以KB为单位的大小,如果是字符串,则可以使用(B, KB, MB, or GB)为单位,比如’2MB’;

如果设置为0则表示无限制

fileTypeDesc

‘All Files’

fileTypeExts

.

设置可以选择的文件的类型,格式如:’.doc;.pdf;*.rar’ 。

formData

JSON格式上传每个文件的同时提交到服务器的额外数据,可在’onUploadStart’事件中使用’settings’方法动态设置。

height

设置浏览按钮的高度 ,默认值

itemTemplate

false

用于设置上传队列的HTML模版,可以使用以下标签:
instanceID – Uploadify实例的ID
fileID – 列队中此文件的ID,或者理解为此任务的ID
fileName – 文件的名称
fileSize – 当前上传文件的大小
插入模版标签时使用格式如:${fileName}

method

Post

提交方式Post或Get

multi

true

设置为true时可以上传多个文件。

overrideEvents

设置哪些事件可以被重写,JSON格式,如:’overrideEvents’ : [‘onUploadProgress’]

preventCaching

true

如果为true,则每次上传文件时自动加上一串随机字符串参数,防止URL缓存影响上传结果

progressData

‘percentage’

设置上传进度显示方式,percentage显示上传百分比,speed显示上传速度

queueID

false

设置上传队列容器DOM元素的ID,如果为false则自动生成一个队列容器。

queueSizeLimit

999

队列最多显示的任务数量,如果选择的文件数量超出此限制,将会出发onSelectError事件。
注意此项并非最大文件上传数量,如果要限制最大上传文件数量,应设置uploadLimit。

removeCompleted

true

是否自动将已完成任务从队列中删除,如果设置为false则会一直保留此任务显示。

removeTimeout

如果设置了任务完成后自动从队列中移除,则可以规定从完成到被移除的时间间隔。

requeueErrors

false

如果设置为true,则单个任务上传失败后将返回错误,并重新加入任务队列上传。

successTimeout

文件上传成功后服务端应返回成功标志,此项设置返回结果的超时时间

swf

‘uploadify.swf’

uploadify.swf 文件的相对路径。

uploader

uploadify.php

后台处理程序的相对路径。

uploadLimit

999

最大上传文件数量,如果达到或超出此限制将会触发onUploadError事件。

width

120

设置文件浏览按钮的宽度。

第二步:

后端修改

由于项目后端使用的Spring Boot,本身也就是使用的Spring MVC文件上传部分,Spring MVC使用的是已经对Servlet文件上传封装了的MultipartResolver接口及其相关实现类和一些相关的类,具体的可以看Spring MVC文件上传源码部分,认为Spring源码还是需要读的,我们只要在Spring Boot启动类中注入这个Bean,或者自行写一个WebConfig配置类,注入一些Web相关的Bean即可,这样Spring Boot启动就会加载配置类,也需要自己写拦截器和全局AOP切面,去捕捉文件上传大小超过限制的异常处理等

基于Spring MVC文件上传组件MultipartResolver接口(核心),使用其中的CommonsMultipartResolver(实现了MultipartResolver接口)这个实现类,CommonsMultipartResolver中的maxUploadSize属性是它继承的抽象父类CommonsFileUploadSupport,这个抽象类其中的一个属性是FileUpload类,而这个类又继承自FileUploadBase这个抽象类,其中它的private long sizeMax = -1;就是maxUploadSize属性的最终设置地方。-1表示文件上传大小没有限制,但是我们一般都会设置一个限制值,这里设置的是210763776,这个值的单位是字节,我们将它设置为525336576字节,也就是501M的大小限制。

修改完以上前端和后端,提交修改的代码到git上即可。

第三步:

Nginx配置

进入到项目部署发布所在的Linux下,进入nginx服务器所安装的目录,

进入到nginx服务器所安装的目录

进入到nginx服务器目录下的conf目录

查看nginx.conf配置文件内容中的client_max_body_size配置的大小,这里设置的是300M。

使用vi或者vim打开nginx.conf配置文件,修改client_max_body_size的大小为501M,保存即可

进入到nginx服务器下的sbin目录下,我们使用./nginx -t查看配置文件是否成功使用,然后使用./nginx -s reload重启Nginx服务器即可。

第四步:

Tomcat配置

由于项目使用的是Spring Cloud,自然使用Spring Boot,我们这个项目还是使用外置的Tomcat作为他的服务器,便于我们对Tomcat服务器进行优化和设置。

进入到项目使用的Tomcat服务器的目录

进入到指定项目使用的Tomcat服务器的目录

进入到Tomcat服务器下的conf配置目录中

看到server.xml配置文件后

先行查看Tomcat服务器的配置,其中两个属性对于这次是比较重要的一个是connectionTimeout这个连接超时时间设置以及默认的maxPostSize属性的设置

使用vi或者vim打开server.xml配置文件,修改connectionTimeout的大小为2000000,这个属性的单位是毫秒,换算之后大概是半个小时,我们配置缺省的maxPostSize属性的值,默认情况下它的值是2097152,它的单位是字节,也就是2M的大小,修改完保存即可

修改完服务器之后,使用发布工具重新从git上拉取最新的代码和部署发布,重新启动脚本即可完成修改,再次尝试大文件上传,功能基本实现。

欢迎入群一起讨论:374992201

Original: https://www.cnblogs.com/songsu/p/14927001.html
Author: Xproer-松鼠
Title: html大文件传输讨论

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/546082/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 预训练模型简要介绍

    从字面上看,预训练模型(pre-training model)是先通过一批语料进行训练模型,然后在这个初步训练好的模型基础上,再继续训练或者另作他用。这样的理解基本上是对的,预训练…

    技术杂谈 2023年7月11日
    0111
  • tolua杂记

    1 字符串调用luaFunc :DoString public class CallLuaFunction : MonoBehaviour { private string scr…

    技术杂谈 2023年5月31日
    079
  • 锁释放和事务提交的顺序问题

    面对高并发是锁的实现要使用aop 实现,锁不能加在方法中,应为事务一般是方法结束后提交,而锁在finally 方法中提交,从而会出现锁已经解锁而事务还没来得及提交,下个锁获得到的数…

    技术杂谈 2023年6月1日
    0113
  • Docker的常用基本命令

    基本命令 官网:https://docs.docker.com/engine/reference/commandline/docker/ 查看容器CPU状态 docker stat…

    技术杂谈 2023年7月24日
    0102
  • 什么是回表,怎么解决?

    表tbl有a,b,c三个字段,其中a是主键,b上建了索引,然后编写sql语句SELECT * FROM tbl WHERE a=1这样不会产生回表,因为所有的数据在a的索引树中均能…

    技术杂谈 2023年7月25日
    090
  • 摆了

    ; ; 这段时间只放板子了。为什么不写题解?答:rt。 posted @2022-01-10 16:35 T_X蒻 阅读(30 ) 评论() 编辑 Original: https:…

    技术杂谈 2023年6月21日
    095
  • EBS多语言小地球

    posted @2018-06-03 10:24 全威儒 阅读(565 ) 评论() 编辑 Original: https://www.cnblogs.com/quanweiru/…

    技术杂谈 2023年6月1日
    090
  • Flink DataStream API

    DataStream API主要可为分为三个部分,DataSource模块、Transformation模块以及DataSink模块。 DataSource模块 内置DataSou…

    技术杂谈 2023年7月10日
    093
  • 「免费开源」基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之动态表单(五)

    基于Vue和Quasar的前端SPA项目实战之动态表单(五) 回顾 通过上一篇文章基于Vue和Quasar的前端SPA项目实战之序列号(四)的介绍,我们已经完成了元数据中序列号的增…

    技术杂谈 2023年7月24日
    0102
  • 从KeyStore中获取PublicKey和PrivateKey

    KeyStore(译:密钥存储库) 代表用于加密密钥和证书的存储设施。 KeyStore 管理不同类型的 entry(译:条目)。每种类型的 entry 都实现了 KeyStore…

    技术杂谈 2023年7月23日
    069
  • container容器

    container为容器型元素,内部可包含其他任何类型的view元素 属性 说明 type(layout子属性) 布局类型:linearLayout——线性布局absoluteLa…

    技术杂谈 2023年6月1日
    0102
  • 禁用Windows重复数据删除

    重复数据删除,可以减少磁盘占用,但使用不当也有可能增加IO,另外,也为此功能会将硬盘分块,所以当硬盘占用较高时,进行碎片整理也比较困难,所以有时需要禁用掉重复数据删除功能,并解除重…

    技术杂谈 2023年5月31日
    098
  • Optional用法与争议点

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介 要说Java中什么异常最容易出现,我想NullPointerException一定当仁不让,为…

    技术杂谈 2023年7月25日
    090
  • H3C CSMA/CA

    posted @2019-09-22 22:24 樊伟胜 阅读(339 ) 评论() 编辑 Original: https://www.cnblogs.com/fanweishen…

    技术杂谈 2023年5月30日
    0107
  • vscode安装与使用详解,解决频繁输入密码验证问题

    vscode下载链接 https://code.visualstudio.com/docs/?dv=win 一、ssh协议,密码方式连接linux 二、ssh协议,公钥方式连接li…

    技术杂谈 2023年5月31日
    097
  • 初识Python系列(一)

    对于Python selenium操作的总结(一) 1.对于驱动的安装 驱动包:webdriver(在cmd执行help(webdriver)可查看所支持的浏览器类型,在此只提其中…

    技术杂谈 2023年7月23日
    082
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球