关于php上传文件过大的表单回填
也许标题有点绕口,有点无法让人理解。请原谅博主,语文学的不好,都赖体育老师。
问题场景重现:在某次迭代中,接到这样一个需求:当新建或编辑一个Bug(包含附件以及其他字段)上传附件过大时,退回到编辑页面,并保证数据回显。
看上去是一个很简单的问题,当附件过大时,页面重新跳转到编辑页面并回传之前Post过去的数据。可是问题来了。php.ini配置文件中upload_max_filesize的设置会限定服务器所能接受上传文件的大小。当上传的文件超过upload_max_filesize时,会拒绝改post请求,并且清空整个post数据。说明白点,除开附件数据,连同其他表单数据也一同清除了,这就导致了没有办法进行表单数据回显。
首先想到的办法是看配置文件中是否可以设置相关属性。可惜未遂,好像并不能解决上传文件过大又保留post数据的方法。然后,只能从其他方面下手。在和别人的讨论中,我逐渐尝试了3个方法。
提交前先进行保存草稿。我们的项目中,有草稿这个设置。但是,很快就被产品人员给否决了。理由简单表述如下:如果一个用户新建一个Bug,提交前保存一份草稿。当他提交失败后决定放弃此次新建,那么数据库中就会多一个没有指向现有Bug的草稿,造成脏数据和空间的浪费。我觉得有道理,否决之。
对附件单独处理进行异步提交。这也是很显而易见的想法。既然附件对提交有影响,那就对其单独处理,异步提交。可是,在以下这个场景中就显得不合适了。当一个用户新建一个Bug时,你异步提交附件,可是此时还未生成此Bug,你异步提交到哪去呢?去绑定哪一个Bug呢?显然在此场景下,又导致了这个方法的失败,不过看来已经比之前前进蛮多了。
在表单提交之前先进行一次Ajax提交用以保存其他数据。简而言之,表单的提交分为两步。第一步:Ajax提交表单数据,不写入数据库,只是单纯的保存表单数据到缓存中并生成一个cache_key用以保存。第二步:带上第一步的cache_key进行表单提交,如果失败,利用cache_key进行表单回填,如果成功,最好如此。
这里就要提到Ajax技术了。AJAX即“Asynchronous JavaScript and XML”(异步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。即可以在不刷新整个页面的前提下,对部分HTML节点进行更新。好像自从google百度地图运用后,良好的交互方式就使其慢慢火起来了。。。好,扯远了,回来。
我们可以利用Jquery,很方便的实现一个Ajax提交。
jQuery.ajax( options ) : 通过 HTTP 请求加载远程数据。
这个是jQuery 的底层 AJAX 实现。简单易用的高层实现见 $.get, $.post 等。
$.ajax() 返回其创建的 XMLHttpRequest 对象。大多数情况下你无需直接操作该对象,但特殊情况下可用于手动终止请求。
注意: 如果你指定了 dataType 选项,请确保服务器返回正确的 MIME 信息,(如 xml 返回 "text/xml")。错误的 MIME 类型可能导致不可预知的错误。见 Specifying the Data Type for AJAX Requests 。
当设置 datatype 类型为 'script' 的时候,所有的远程(不在同一个域中)POST请求都回转换为GET方式。
$.ajax() 只有一个参数:参数 key/value 对象,通常记为operations,包含各配置及回调函数信息。详细参数选项,可进官网查看。
这是页面上的一段代码,用来绑定Ajax提交事件。
$('#id-tapd-toolbar').find('.for_submit').each(function() {
var ele_submit = document.getElementById('save' + this.id);
$(this).click(function() {
var attachment_p = $('.attach_field_1');
if(attachment_p.length != 0){
var new_form_action = $('#bug_form').attr('action').replace(/submit/, 'ajax_submit');
var editor = TFL.editor.getInstance("BugDescription");
var description = editor.html();
$('#BugDescription').text(description);
jQuery.ajax({
url: new_form_action, // 提交的页面
data: $('#bug_form').serialize(), // 从表单中获取数据
type: "POST", // 设置请求类型为"POST",默认为"GET"
beforeSend: function() // 设置表单提交前方法
{
// 按钮灰化
},
error: function(request) { // 设置表单提交出错
alert(<?php t("failed to submit the form ,please try it later.") ?>);
},
success: function(msg) {
var cacheKey = msg;
var old_url = $('#bug_form').attr('action');
var new_url = old_url + "&cache_key=" + cacheKey;
$('#bug_form').attr('action', new_url); //更新表单的action,带上cache用于回显
ele_submit.click();
}
});
} else{
ele_submit.click();
}
});
});
可能注释会影响到代码的阅读。我就按照代码的顺序,简单的说一下思路。
首先,变量ele_submit得到提交按钮的ID,如果当前包含附件提交的话,那么将表单提交的url改为ajax_submit。变量description是对富文本框的特殊处理。jQuery.ajax()是接下来的重点。可见ajax方法的参数就是一些key/value值,简单明了。url指明提交的页面;data指明提交时包含的数据;type表明请求类型;beforeSend是提交前的方法,例如对页面元素和数据的处理等;error指明提交失败后执行的内容,譬如弹窗报错等;success指明提交成功后的执行内容,参数即为响应数据。
重点看一下success里面的方法。显然ajax_submit请求会返回一段缓存key值cache_key,并加在表单的旧url上,最后进行表单提交。应该是清晰明了的代码吧。
下面贴下服务器端的代码:
function ajax_submit(){
$ajax_result = array();
$this->layout = "ajax";
$cache_key = 'SUBMIT_BUG_WITH_ATTACHMENT_' . time();
MyCache::add($cache_key, $this->data, '+5 mins');
echo $cache_key;
exit;
}
很简单,用post过来的数据生成一个缓存,并将缓存key响应回去给ajax的success方法。
接下来,是当失败后回填数据的代码,也很简单,只要保证数据字段对应就行了。
if(isset($this->params['url']['cache_key'])){ //第一次提交后会有cache_key,用以保存表单数据
$temp_key = $this->params['url']['cache_key'];
$old_data = MyCache::get($temp_key);
$this->set("old_data", $old_data);
if(isset($old_data['BugStoryRelation']['BugStoryRelation_relative_id'])){
$fields['BugStoryRelation_relative_id']['default']=$old_data['BugStoryRelation']['BugStoryRelation_relative_id'];
}
foreach ($old_data['Bug'] as $key => $value) { //用cache里面的数据更新fields,保证当数据过大时数据能正确回显 by jeremy
if(!empty($value) && array_key_exists($key, $fields)){
if(is_array($value)){
$fields[$key]['default'] = $value[0];
} else{
$fields[$key]['default'] = $value;
}
}
}
}
还有一些特殊需要处理的地方,不是本文的重点,就不列举了。
总之,这是一次很好的Ajax实践,jQuery封装的很好,在实现的过程中,暴露了自己对前端技术知识的漏洞,以后要找机会慢慢加强这方面的锻炼。
另外,三天后就离开腾讯结束自己的实习生活了,心有不舍,自己也在腾讯的代码库中留下了自己的印迹,不知道能保存多久呢。。。此时正在为导出Excel的一个问题伤神。在测试环境上好用,在正式环境下出问题,Bug都不好定为,真是蛋疼。。。。
关于php上传文件过大的表单回填的更多相关文章
- JSP SMARTUPLOAD组件:上传文件时同时获取表单参数
原因很简单: 注意更改from 属性啊!否则为null! 因为你用jspsmartuploadsmart时post请求 的格式是multipart/form-data,即enctype="m ...
- ajax上传文件 基于jquery form表单上传文件
<script src="/static/js/jquery.js"></script><script> $("#reg-btn&qu ...
- [转]javascript实现限制上传文件的大小
本文转自:http://www.micmiu.com/lang/javascript/js-check-filesize/ 目录 基本思路 示例 [一].基本思路 在FireFox.Chrome浏览器 ...
- 使用WebClient上传文件并同时Post表单数据字段到服务端
之前遇到一个问题,就是使用WebClient上传文件的同时,还要Post表单数据字段,一开始以为WebClient可以直接做到,结果发现如果先 Post表单字段,就只能获取到字段及其值,如果先上传文件 ...
- HTML上传文件支持大文件上传,下载
上传 1.修改配置文件web.config,在<system.webServer>下面加入 <security> <requestFiltering > <r ...
- .net上传文件,大文件及下载方式汇总(转)
原文地址:http://www.360doc.com/content/19/1219/10/67993814_880731215.shtml Brettle.Web.NeatUpload.dll 文件 ...
- Form key length limit 2048 exceeded ,提交数据时,数据的键过长 或者是上传文件过大
在ASP.NET Core MVC中,文件的key 默认最大为2048,文件上传的最大上传文件默认为20MB,如果我们想上传一些比较大的文件,就不知道怎么去设置了,没有了Web.Config我们应该如 ...
- js上传文件过大导致上传失败原因以及解决办法
背景:项目需要用到上传视频功能,由于视频有知识产权,要求必须上传到自己的服务器上不允许用第三方视频网站接口上传,于是一开始开始用的是input type=file去上传,小的视频上传没有问题,上传将近 ...
- c# 模拟表单提交,post form 上传文件、大数据内容
表单提交协议规定:要先将 HTTP 要求的 Content-Type 设为 multipart/form-data,而且要设定一个 boundary 参数,这个参数是由应用程序自行产生,它会用来识别每 ...
随机推荐
- JS设计模式——7.工厂模式(概念)
工厂模式 本章讨论两种工厂模式: 简单工厂模式 使用一个类(通常是一个单体)来生成实例. 使用场景:假设你想开几个自行车商店(创建自行车实例,组装它,清洗它,出售它),每个店都有几种型号的自行车出售. ...
- cdn_一些常用的cdn地址
https://code.jquery.com/jquery-3.3.1.jshttps://cdn.bootcss.com/jquery/2.1.4/jquery.min.js https://cd ...
- 技术分享:如何在PowerShell脚本中嵌入EXE文件
技术分享:如何在PowerShell脚本中嵌入EXE文件 我在尝试解决一个问题,即在客户端攻击中只使用纯 PowerShell 脚本作为攻击负荷.使用 PowerShell 运行恶意代码具有很多优点, ...
- 2017-2018-2 20179205《网络攻防技术与实践》Windows攻击实验
Windows攻击实验 实验描述: 使用Metaspoit攻击MS08-067,提交正确得到远程shell过程的截图(不少于五张). MS08-067漏洞介绍 MS08-067漏洞的全称为&quo ...
- Flip Bits
Determine the number of bits required to flip if you want to convert integer n to integer m. Notice ...
- Django-模板继承、包含和静态文件配置
一.模板继承 模板继承可以减少页面内容的重复定义,实现页面内容的重用 典型应用:网站的头部.尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义 block标签:在父模板中预留区域,在子模板 ...
- 关于更新SQLserver统计信息的存储过程
1.建立t_mon_table_stat 用于存过需要更新统计信息的表 2.查找需要更新统计信息的表 insert into t_mon_table_stat SELECT DISTINCT SP.r ...
- windows 依赖查看
使用工具Download Process Explorer查看运行程序所依赖的动态库. 中文说明:适用于 Windows 的 Process Explorer 10.21 版
- 根据条件批量删除document
curl -H "Content-Type:application/json" -XPOST http://localhost:9200/devopsrealinfo/_dele ...
- 一步一步学习IdentityServer3 (7)
在介绍自定义用户服务之前先对IdentityServerServiceFactory说明下 Idr3的服务工厂 下面有很多idr3提供的接口服务, 如:ViewService.UserService. ...