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 相关文章推荐
从零开始 教你如何搭建Discuz!4.1论坛
Jul 07 PHP
谈谈PHP语法(2)
Oct 09 PHP
简单的php 验证图片生成函数
May 21 PHP
用php或asp创建网页桌面快捷方式的代码
Mar 23 PHP
PHP curl 获取响应的状态码的方法
Jan 13 PHP
PHP三元运算的2种写法代码实例
May 12 PHP
CI框架验证码CAPTCHA辅助函数用法实例
Nov 05 PHP
PHP将URL转换成短网址的算法分享
Sep 13 PHP
php基于闭包实现函数的自调用(递归)实例分析
Nov 11 PHP
常用PHP封装分页工具类
Jan 14 PHP
thinkPHP框架实现图像裁剪、缩放、加水印的方法
Mar 14 PHP
PHP中soap用法示例【SoapServer服务端与SoapClient客户端编写】
Dec 25 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
PHP5中新增stdClass 内部保留类
2011/06/13 PHP
PHP内核探索:变量概述
2014/01/30 PHP
PHP 只允许指定IP访问(允许*号通配符过滤IP)
2014/07/08 PHP
试用php中oci8扩展
2015/06/18 PHP
phpMyAdmin安装并配置允许空密码登录
2015/07/04 PHP
PHP中使用curl伪造IP的简单方法
2015/08/07 PHP
php插件Xajax使用方法详解
2017/08/31 PHP
微信公众平台开发教程⑤ 微信扫码支付模式介绍
2019/04/10 PHP
Javascript 学习书 推荐
2009/06/13 Javascript
Dom 是什么的详细说明
2010/10/25 Javascript
解决自定义$(id)的方法与jquery选择器$冲突的问题
2014/06/14 Javascript
jQuery对象的length属性用法实例
2014/12/27 Javascript
javascript面向对象之访问对象属性的两种方式分析
2015/01/13 Javascript
Vue.js实现无限加载与分页功能开发
2016/11/03 Javascript
学习vue.js计算属性
2016/12/03 Javascript
gulp解决跨域的配置文件问题
2017/06/08 Javascript
JavaScript引用类型RegExp基本用法详解
2018/08/09 Javascript
vue车牌号校验和银行校验实战
2019/01/23 Javascript
前端Electron新手入门教程详解
2019/06/21 Javascript
JavaScript实现京东快递单号查询
2020/11/30 Javascript
python使用xlrd实现检索excel中某列含有指定字符串记录的方法
2015/05/09 Python
Python导出数据到Excel可读取的CSV文件的方法
2015/05/12 Python
Python判断文本中消息重复次数的方法
2016/04/27 Python
Python+selenium 获取一组元素属性值的实例
2018/06/22 Python
python被修饰的函数消失问题解决(基于wraps函数)
2019/11/04 Python
在pycharm中实现删除bookmark
2020/02/14 Python
学python最电脑配置有要求么
2020/07/05 Python
日本航空官方网站:JAL
2019/06/19 全球购物
销售高级职员求职信
2013/10/29 职场文书
电脑饰品店的创业计划书
2014/01/21 职场文书
怎么写自荐书范文
2014/02/12 职场文书
竞聘演讲稿怎么写
2014/08/28 职场文书
服务员态度差检讨书
2014/10/28 职场文书
小学教师教育随笔
2015/08/14 职场文书
手把手教你从零开始react+antd搭建项目
2021/06/03 Javascript
《艾尔登法环》发布最新「战技」宣传片
2022/04/03 其他游戏