PHP 文件上传后端处理实用技巧方法


Posted in PHP onJanuary 06, 2017

PHP 文件上传后端处理实用技巧方法

引语:在上一篇文章中说到,在页面中可以用隐藏的方式让你的上传页面看起来漂亮。但是这对于性能来说,并没有什么卵用,那么在后台的处理中,难道就没有一些处理技巧么?所谓后台的技巧,应该要包括上传得快一点,上传的文件大一点!那么,本文就来说说,后端处理都有些什么技巧吧!

业务场景一、我们只会选择一个单个的文件上传,而且不需要做一些即时的验证工作。那么,也许并没有什么优化可言了,因为,最后你要做的,只是将这个文件放在表单里最后一起提交,直接处理即可!

业务场景二、需要上传多个文件,而且需要时时验证文件内部内容,并时行相应页面显示。对于这种况,在用户选择了上传文件之后,我们需要立即将文件上传,因为我们需要读取文件里的信息,在最后提交的时候,我们也需要提交一次文件。很明显,在这里是存在一个重复上传的工作的,一个耗费用户时间,二个是耗费服务器带宽资源!优化,能够想得到的方法也很简单,能不能在第一次上传完文件之后,就将文件保留在服务器,真正提交表单的时候,去读取这个已经被上传的临时文件即可。是的,这就是我们的处理思路!

业务场景三、与场景二类似,需要上传多个文件,但是多个文件可能是分开上传的。即我们可能第一次上传了10M,第二次上传了10M,总共上传了10次,那么,在服务器端来说的话,一次性提交肯定是超出了上传大小的限制了,但是如果,我们是分每一次的上传,这是可以的,而最后提交的时候,我们只需要将简短的文本信息传上去即可!

思路的确是简单的,看起来,也是没什么问题,但是,也许我是能力有限,当时着实花了我不少时间去处理这个什么鬼!下面,我将给出一些示例代码,以供参考:

文件上传技巧(将单次上传的文件作为临时文件存在在服务器端)示例代码:

1. 页面js处理

//点击选择完成文件后,触发上传文件操作,将文件上传至服务器临时目录
  $('.upload-real-file').off().on('change', function(){
   if(!$(this).val()){
    return false;
   }
   var responseObjId = $(this).attr('response-id');
   var responseObj = $('#' + responseObjId);
   $('#Form').ajaxSubmit({
    url:'/aa/bb/uploadTmpApkTool',
    resetForm: false,
    dataType: 'json',
    beforeSubmit: function(option){
     window.loading = layer.load(2);
    },
    success: function(data, statusText){
     layer.close(window.loading);
     if(data.status == 1){
      responseObj.html(data.apkInfoHtml);
      var parentContainer = responseObj.parent().parent(),
       nameContainer = parentContainer.find('.file-name-container');
      nameContainer.html(data.apkName);
      nameContainer.attr('title', data.apkName);
      responseObj.find('.file-tmp').html(data.fileInfo); //将文件信息存放于隐藏域中,以便在提交时能找到 
      $(submitId).removeAttr('disabled');
     }else{
      layer.alert(data.info);
     }
    },
    error: function(data){
     layer.close(window.loading);
     layer.alert('未知错误,请稍后再试!');
    }
   });
   return false;//防止dialog 自动关闭
  });

2. 很明显,页面里面需要获取文件信息,后台处理代码(PHP)

$apkConfig = $this->_getApkConfig();
  $params = $this->getFilteredParam('get');
  $subFile = $_FILES['apkToolFiles'];
  $apkName = $apkInfoHtml = "";
  if(empty($subFile))
  {
   $this->ajaxReturn(array('status' => -4, 'info' => '请选择要上传的文件'));
  }

  foreach ($subFile['name'] as $subKey => $subVal)
  {
   if ($subFile['name'][$subKey])
   {
    $fileData = $this->_getFileData($subFile, $subKey);
    $checkData = array(
     'maxSize' => $apkConfig['FILE_MAX_SIZE'],
     'savePath' => $apkConfig['TMP_CHILD_PATH'],
     'extArr' => array('apk'),
     'releaseName' => str_replace('.apk', '', $fileData['fileName']), //特有
    );
    $checkResult = $this->_checkFileData($fileData, $checkData);
    if ($checkResult['status'] != 1)
    {
     $this->ajaxReturn($checkResult);
    }
    //移动文件
    $filePath = $checkData['savePath'] . '/' . $fileData['fileName'] . '.tmp' . genRandStr(6);;
    $this->_moveUploadedFile($fileData['tmpName'], $filePath);
    $apkInfo = $this->_apkParser($filePath); //解析
    if($apkInfo['UMENG_CHANNEL'] != 'UMENG_CHANNEL_VALUE')
    {
     @unlink($filePath);        //删除无效文件
     $this->ajaxReturn(array('status' => 0, 'info' => "UMENG_CHANNEL的值要是 UMENG_CHANNEL_VALUE才行"));
    }
    $tmpFileArr['file_info'] = array(
     'name' => $subFile['name'][$subKey],
     'type' => $subFile['type'][$subKey],
     'tmp_name' => str_replace($apkConfig['TMP_CHILD_PATH'] . '/', '', $filePath),
     'error' => $subFile['error'][$subKey],
     'size' => $subFile['size'][$subKey],
    );    //转存该值,不再重复上传文件
   }
   else
   {
    $this->ajaxReturn(array('status' => 0, 'info' => "文件不能为空"));
   }
   foreach ($apkInfo as $key => $val)
   {
    $apkInfoHtml .= "{$key}:{$val} \r\n";
   }
   $apkName = $fileData['fileName'];
   $version = $apkInfo['versionName'];
  }
  $fileInfo = htmlspecialchars(json_encode($tmpFileArr['file_info']));
  $fileInfoHtml = "<input name=\"apkToolFileTmp[]\" value='{$fileInfo}' type=\"hidden\"/>"; //一定要输出前使用htmlspecialchars, 否则不能正确显示页面值和获取至正确的文件信息

  $this->ajaxReturn(array('status' => 1, 'info' => "上传成功", 'version' => $version, 'item' => $item, 'apkName' => $apkName, 'apkInfoHtml' => $apkInfoHtml, 'fileInfo' => $fileInfoHtml));
 }

3. 通过以两部分代码的配合,我们在页面上已经有正确的信息了,只需要在最后提交表单的时候, 不要将文件提交到服务器,在服务器端处理时,只需将之前上传的临时文件移动一下位置即可 ,这样就算大功告成了!

$('.upload-file-real').attr('disabled', 'disabled');  //提交表单前,禁用上传文件

4. 后续工作

将临时文件上传到服务器后,是没办法判断用户是否取消当前操作的,如果取消了,则临时文件将一直存在于服务器,所以,我们需要一个定时清理临时目录的脚本。当然,这个很简单,就只需要找到这个目录,比较一下时间,比如超过一天前的文件就给删除。注意控制清理频率即可!

5. 题外话

日志真的很重要,哪里出错了,哪里删除文件了,哪里清理数据库了,一定要做好记录,否则,到时查找原因时,到哪里去喊救命!

上传文件到服务器临时目录,后端处理原理看起来很简单,但是也需要你仔细调试,至少当初我在做这个小功能时,着实费了不少劲才缕清楚的!

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

PHP 相关文章推荐
PHP字符串 ==比较运算符的副作用
Oct 21 PHP
用php的ob_start来生成静态页面的方法分析
Mar 09 PHP
php 大数据量及海量数据处理算法总结
May 07 PHP
深入PHP中的HashTable结构详解
Jun 13 PHP
排序算法之PHP版快速排序、冒泡排序
Apr 09 PHP
php实现根据词频生成tag云的方法
Apr 17 PHP
php链表用法实例分析
Jul 09 PHP
谈谈PHP中substr和substring的正确用法及相关参数的介绍
Dec 16 PHP
Joomla调用系统自带编辑器的实现方法
May 05 PHP
简单解析PHP程序的运行流程
Jun 23 PHP
php日期操作技巧小结
Jun 25 PHP
thinkphp自定义权限管理之名称判断方法
Apr 01 PHP
PHP+mysql实现从数据库获取下拉树功能示例
Jan 06 #PHP
php中简单的对称加密算法实现
Jan 05 #PHP
WAF的正确bypass
Jan 05 #PHP
phpcms的分类名称和类别名称的调用
Jan 05 #PHP
php 5.4 全新的代码复用Trait详解
Jan 05 #PHP
golang 调用 php7详解及实例
Jan 04 #PHP
PHP 与 UTF-8 的最佳实践详细介绍
Jan 04 #PHP
You might like
PHP安装全攻略:APACHE
2006/10/09 PHP
解析php dirname()与__FILE__常量的应用
2013/06/24 PHP
php获取文件内容最后一行示例
2014/01/09 PHP
php实现将上传word文件转为html的方法
2015/06/03 PHP
php版微信小店API二次开发及使用示例
2016/11/12 PHP
Laravel框架分页实现方法分析
2018/06/12 PHP
laravel框架邮箱认证实现方法详解
2019/11/22 PHP
Laravel Eloquent分表方法并使用模型关联的实现
2019/11/25 PHP
JQuery中each()的使用方法说明
2010/08/19 Javascript
javascript获取URL参数与参数值的示例代码
2013/12/20 Javascript
一个简单的jquery进度条示例
2014/04/28 Javascript
AngularJS 整理一些优化的小技巧
2016/08/18 Javascript
vuejs2.0子组件改变父组件的数据实例
2017/05/10 Javascript
JavaScript实现跟随滚动缓冲运动广告框
2017/07/15 Javascript
vue在使用ECharts时的异步更新和数据加载详解
2017/11/22 Javascript
详解在create-react-app使用less与antd按需加载
2018/12/06 Javascript
关于js陀螺仪的理解分析
2019/04/11 Javascript
js的新生代垃圾回收知识点总结
2019/08/22 Javascript
layer.js open 隐藏滚动条的例子
2019/09/05 Javascript
vue实现评论列表功能
2019/10/25 Javascript
Python实现把xml或xsl转换为html格式
2015/04/08 Python
对Python闭包与延迟绑定的方法详解
2019/01/07 Python
详解Python解决抓取内容乱码问题(decode和encode解码)
2019/03/29 Python
Python中的引用知识点总结
2019/05/20 Python
使用matlab或python将txt文件转为excel表格
2019/11/01 Python
Python xml、字典、json、类四种数据类型如何实现互相转换
2020/05/27 Python
python怎么删除缓存文件
2020/07/19 Python
GWT的应用有哪两种部署模式
2012/12/21 面试题
新郎父亲婚宴答谢词
2014/01/11 职场文书
法制宣传月活动总结
2014/04/29 职场文书
预备党员转正考核材料
2014/06/03 职场文书
2015年党员岗位承诺书
2015/04/27 职场文书
预备党员转正意见
2015/06/01 职场文书
乡镇干部学习心得体会
2016/01/23 职场文书
OpenCV-Python实现轮廓的特征值
2021/06/09 Python
React自定义hook的方法
2022/06/25 Javascript