目录
我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成
一、前言
 二、生成excel文件
 三、让程序在后台执行
 四、显示文件生成进度
 五、下载文件
 六、上线后出现的问题
 七、相应的后续优化
 八、后记
首页 后端开发 php教程 我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成_PHP教程

我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成_PHP教程

Jul 13, 2016 am 09:44 AM

我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成

一、前言

    记录一下以前做的后台excel格式导出统计信息的功能,也是最近同事问到了相关东西,一时之间竟忘了具体的细节,因此记录一下;

    大家知道,excel导出数据的功能,后台几乎是必须功能,一般都是点击后,生成文件然后自动下载,

    如果是数据量小的话,一下子便可请求完成,从而下载到本地;

    但是,如果数据量特别大的时候,页面就必须一直在等待,直到写入excel成功,

    这样便影响了后台使用者无法操作其他页面,为此,对excel导出做了以下功能优化:

登录后复制
登录后复制

二、生成excel文件

生成excel文件的方法有很多,暂不一一记录,只是记录本次的方法;

这里用到了table的html格式,以及相应的excel的声明

(隐约记得其他的方法用office07打开的时候好像是乱码,后面尝试用csv格式文件,可还是乱码,所以用了table的形式)

文件的开头:

我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成_PHP教程 1 $struserdata = <<<Eof 2 3 xmlns:x="urn:schemas-microsoft-com:office:excel" 4 xmlns="http://www.w3.org/TR/REC-html40"> 5 6 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 7 8 9 10 12 13 14
15 16 17 Eof;View Code

文件的结尾:

我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成_PHP教程1 $struserdata = <<<Eof 2
3
4 5 6 Eof; View Code

当然,文件中间就是一些tr td 标签了。

三、让程序在后台执行

<p><span>    场景:</span></p>
<p><span>        用户点击 生成excel后,跳转到下载页面,程序在后台执行,用户可不必等待生成完成,可执行其他操作;</span></p>
<p><span>        下载页面可看到文件生成的进度以及是否可下载状态</span></p>
<p><span>    思路:</span></p>
<p><span>        点击 生成excel,显示下载页面  ---> show_download方法</span></p>
<p><span>        生成excel ---> create_excel 方法</span></p>
登录后复制

show_download方法中调用 create_excel方法,而show_download 方法中,自己用了一下命令行执行程序的方式,

利用php命令行的方式,把参数传递给 create_excel方法

<span><span>1</span>  <span>//</span><span> $cmd = "/usr/bin/php  /home/xxx/xxx.php " . $strjoin . "  >/dev/null & ";
</span><span>2</span> <span> // $a=exec($cmd, $out, $returndata);</span>
<span>3</span>  
<span>4</span>  
<span>5</span>  <span>$command</span> = "/usr/bin/php ".STATISTIC_EXPORT_SCRIPT_DIR."xxx.php " . "'" .<span>$strjoin</span> ."'". " " . <span>$uid</span> . " ". <span>$action</span> ."  & "<span>;
</span><span>6</span>  <span>$process</span> = <span>proc_open</span>(<span>$command</span>, <span>array</span>(),<span>$pipes</span><span>); 
</span><span>7</span>  <span>$var</span> = <span>proc_get_status</span>(<span>$process</span><span>); 
</span><span>8</span>  <span>proc_close</span>(<span>$process</span><span>);
</span><span>9</span>  <span>$pid</span> = <span>intval</span>(<span>$var</span>['pid'])+1;</span>
登录后复制

而在create_excel方法中:

需填写以下代码:

<span><span>1</span> <span>set_time_limit</span>(0); <span>//</span><span>取消脚本运行时间的超时上限</span>
<span>2</span> 
<span>3</span> <span>ignore_user_abort</span>(<span>TRUE</span>); <span>//</span><span>后台运行,不受用户关闭浏览器的影响</span></span>
登录后复制

调用相关的api得到数据:

<span><span>1</span> <span>$statistic</span> = <span>call_user_func</span>(<span>array</span>('shellscript','get_result'),<span>$url</span>,<span>$params</span><span>);
</span><span>2</span> <span>if</span>(!<span>is_object</span>(<span>$statistic</span>) || !<span>isset</span>(<span>$statistic</span>->data-><span>items)){
</span><span>3</span>     <span>usleep</span>(400000);<span>//</span><span>停止400毫秒</span>
<span>4</span>     <span>$statistic</span> = <span>call_user_func</span>(<span>array</span>('shellscript','get_result'),<span>$url</span>,<span>$params</span><span>);
</span><span>5</span> }</span>
登录后复制

四、显示文件生成进度

但是怎么显示相应的文件生成进度呢,怎么知道文件到底生成好了没有呢?

这里,我用到的方法是,在写入数据文件的时候data.xsl,每个数据文件都生成一个对应的文件进度文件,暂且称为flag_data.xsl;

思路:

登录后复制
登录后复制

查看文件的进度方法:

我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成_PHP教程 1 public function execscript_process(){ 2 $this->load->library('smarty'); 3 $file_arr_str = array(); 4 $file_arr_process = array(); 5 $file_arr_name = array(); 6 $file_arr = array(); 7 $refresh_flag = 'yes'; 8 $uid = $_REQUEST['uid']; 9 $url_dir = STATISTIC_EXPORT_FILE_DIR.$uid .'/';//@todo 10 if(!is_dir($url_dir)){ 11 @mkdir($url_dir,0777); 12 } 13 $files = scandir($url_dir); 14 15 if(!empty($files)){ 16 foreach ($files as $key => $value) { 17 if($value!='.' && $value!='..'){ 18 if(substr($value, 0 , 5)=="flag_"){ 19 $file_size = filesize($url_dir . $value); 20 if(!empty($file_size)){ 21 $fhandle = fopen($url_dir . $value, 'rb+'); 22 fseek($fhandle, -1, SEEK_END); 23 $fstr = ''; 24 while(($c = fgetc($fhandle)) !== false) { 25 if($c == "\n" && $fstr) break; 26 $fstr = $c . $fstr; 27 fseek($fhandle, -2, SEEK_CUR); 28 } 29 fclose($fhandle); 30 $fstr = trim($fstr); 31 $fstr_arr_str = explode(',', $fstr); 32 $file_arr_process[] = 100 * number_format($fstr_arr_str[0]/$fstr_arr_str[1],2).'%'; 33 $file_arr_name[] = substr($value,5); 34 } 35 } 36 } 37 } 38 39 foreach ($file_arr_process as $key => $value) { 40 if($value != '100%'){ 41 $refresh_flag = 'no'; 42 break; 43 } 44 } 45 } 46 47 $file_arr = array( 48 'process' => $file_arr_process, 49 'name' => $file_arr_name, 50 'refresh_flag' => $refresh_flag 51 ); 52 $file_arr_json = json_encode($file_arr); 53 echo $file_arr_json; 54 } View Code

五、下载文件

文件的下载就好说了,既然已经都生成成功,下载的方法如下:

<span><span> 1</span>     <span>public</span> <span>function</span><span> execscript_download(){
</span><span> 2</span>         <span>$filename</span> = <span>$_REQUEST</span>['filename'<span>];
</span><span> 3</span>         <span>$uid</span> = <span>$_REQUEST</span>['uid'<span>];
</span><span> 4</span>         <span>$file_dir</span> = STATISTIC_EXPORT_FILE_DIR.<span>$uid</span>.'/'.<span>$filename</span><span>;
</span><span> 5</span>         <span>if</span> (!<span>file_exists</span>(<span>$file_dir</span><span>)){
</span><span> 6</span>             <span>header</span>("Content-type: text/html; charset=utf-8"<span>);
</span><span> 7</span>             <span>echo</span> "File not found!"<span>;
</span><span> 8</span>             <span>exit</span><span>; 
</span><span> 9</span>         } <span>else</span><span> {
</span><span>10</span>             <span>ini_set</span>("memory_limit","500M"<span>); 
</span><span>11</span>             <span>header</span>('Content-Description: File Transfer'<span>);
</span><span>12</span>             <span>header</span>('Content-Type: application/octet-stream'<span>);
</span><span>13</span>             <span>header</span>('Content-Disposition: attachment; filename='.<span>basename</span>(<span>$file_dir</span><span>));
</span><span>14</span>             <span>header</span>('Content-Transfer-Encoding: binary'<span>);
</span><span>15</span>             <span>header</span>('Expires: ' . <span>gmdate</span>('D, d M Y H:i:s') . ' GMT'<span>);
</span><span>16</span>             <span>header</span>('Cache-Control: must-revalidate,post-check=0, pre-check=0'<span>);
</span><span>17</span>             <span>header</span>('Pragma: public'<span>);
</span><span>18</span>             <span>header</span>('Content-Length: ' . <span>filesize</span>(<span>$file_dir</span><span>));
</span><span>19</span>             <span>readfile</span>(<span>$file_dir</span><span>);
</span><span>20</span> <span>        }
</span><span>21</span> 
<span>22</span>     }</span>
登录后复制

六、上线后出现的问题

本地本来已经测试完毕,可上线后,却出现了奇怪的问题;

<p><span>    现象描述:</span></p>
<p><span>        当在后台点击生成文件,跳转到下载页的时候,因为下载页是显示文件进度的页面,</span><br /><span>        竟然出现有时候有刚刚点击的文件进度,有时候没有,就感觉没有生成相应的文件一样;</span></p>
<p><span>    解决方法:</span></p>
<p><span>        因为数据文件和进度文件都是生成在程序的某个文件夹file中,所以读取的时候都是读取的文件夹下的文件,从而判断显示进度;</span></p>
<p><span>        后面才知道,由于后台程序有两台服务器,导致读取以及下载的时候找不到相应的文件夹,两个服务器相应的文件夹弄个共享目录就可以了</span></p>




登录后复制

七、相应的后续优化

由于下载的文件多了,导致文件夹下的文件越来越多,而原来生成的文件是没有价值的,所以加了个定期删除文件的功能,只保留近七天的文件

当然可以用crontab,只不过我比较懒,是在点击生成文件的时候,判断了一下文件夹中的过期文件,从而删除

<span><span> 1</span>     <span>public</span> <span>function</span><span> execscript_process_show(){
</span><span> 2</span>         <span>$this</span>->load->library('smarty'<span>);
</span><span> 3</span>         <span>$uid</span> = <span>$_REQUEST</span>['uid'<span>];
</span><span> 4</span>         <span>$url_dir</span> = STATISTIC_EXPORT_FILE_DIR.<span>$uid</span> .'/';<span>//</span><span>@todo</span>
<span> 5</span>         <span>if</span>(!<span>is_dir</span>(<span>$url_dir</span><span>)){
</span><span> 6</span>             @<span>mkdir</span>(<span>$url_dir</span>,0777<span>);
</span><span> 7</span> <span>        }        
</span><span> 8</span>         <span>$files</span> = <span>scandir</span>(<span>$url_dir</span><span>);
</span><span> 9</span>         <span>if</span>(!<span>empty</span>(<span>$files</span><span>)){
</span><span>10</span>             <span>foreach</span> (<span>$files</span> <span>as</span> <span>$key</span> => <span>$value</span><span>) {
</span><span>11</span>                 <span>if</span>(<span>$value</span>!='.' && <span>$value</span>!='..'<span>){
</span><span>12</span>                     <span>foreach</span> (<span>$files</span> <span>as</span> <span>$key</span> => <span>$value</span><span>) {
</span><span>13</span>                         <span>if</span>(<span>$value</span>!='.' && <span>$value</span>!='..'<span>){
</span><span>14</span>                             <span>if</span>(<span>substr</span>(<span>$value</span>, 0 , 5)!="flag_"<span>){
</span><span>15</span>                                 <span>$filenamedate</span> = <span>substr</span>(<span>$value</span>, 0,10<span>);
</span><span>16</span>                                 <span>$today</span> = <span>date</span>('Y-m-d',<span>time</span><span>());
</span><span>17</span>                                 <span>$filenamedate</span> = <span>date</span>('Y-m-d',<span>strtotime</span>(<span>$filenamedate</span>)+(STATISTIC_FILE_EXPIRE_DAY-1)*24*3600<span>);
</span><span>18</span>                                 <span>if</span>(<span>$today</span>><span>$filenamedate</span>){<span>//</span><span>文件过期</span>
<span>19</span>                                     @<span>unlink</span>(<span>$url_dir</span> . <span>$value</span><span>);
</span><span>20</span>                                     @<span>unlink</span>(<span>$url_dir</span> . 'flag_' . <span>$value</span><span>);
</span><span>21</span> <span>                                }
</span><span>22</span> <span>                            }
</span><span>23</span> <span>                        }
</span><span>24</span> <span>                    }                    
</span><span>25</span> <span>                }
</span><span>26</span> <span>            }
</span><span>27</span> <span>        }
</span><span>28</span> 
<span>29</span>         <span>$this</span>->smarty->assign('uid',<span>$uid</span><span>);
</span><span>30</span>         <span>$this</span>->smarty->display('interact/statistic/execscript.tpl'<span>);
</span><span>31</span>     }</span>
登录后复制

八、后记

大文件的导出大体就是这个样子,欢迎大家吐槽,共同交流;

当时在用命令行执行方法的时候,也参考了一下相应的资料,记录一下;

<span>http://blog.csdn.net/yysdsyl/article/details/4636457

http://www.codesky.net/article/201202/163385.html

http://www.cnblogs.com/zdz8207/p/3765567.html

http://blog.163.com/mojian20040228@126/blog/static/4112219320097300922992/

http://php.net/manual/en/features.commandline.php

http://blog.csdn.net/yangjun07167/article/details/5603425

http://blog.csdn.net/yunsongice/article/details/5445448

http://www.cppblog.com/amazon/archive/2011/12/01/161281.aspx

http://blog.51yip.com/tag/proc_open

http://www.justwinit.cn/post/1418/

http://limboy.me/tech/2010/12/05/php-async.html</span>
登录后复制

 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1048777.htmlTechArticle我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成 一、前言 记录一下以前做的后台excel格式导出统计信息的功能,也...
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1272
29
C# 教程
1252
24
说明PHP中的安全密码散列(例如,password_hash,password_verify)。为什么不使用MD5或SHA1? 说明PHP中的安全密码散列(例如,password_hash,password_verify)。为什么不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,应使用password_hash和password_verify函数实现安全的密码哈希处理,不应使用MD5或SHA1。1)password_hash生成包含盐值的哈希,增强安全性。2)password_verify验证密码,通过比较哈希值确保安全。3)MD5和SHA1易受攻击且缺乏盐值,不适合现代密码安全。

PHP和Python:比较两种流行的编程语言 PHP和Python:比较两种流行的编程语言 Apr 14, 2025 am 12:13 AM

PHP和Python各有优势,选择依据项目需求。1.PHP适合web开发,尤其快速开发和维护网站。2.Python适用于数据科学、机器学习和人工智能,语法简洁,适合初学者。

PHP行动:现实世界中的示例和应用程序 PHP行动:现实世界中的示例和应用程序 Apr 14, 2025 am 12:19 AM

PHP在电子商务、内容管理系统和API开发中广泛应用。1)电子商务:用于购物车功能和支付处理。2)内容管理系统:用于动态内容生成和用户管理。3)API开发:用于RESTfulAPI开发和API安全性。通过性能优化和最佳实践,PHP应用的效率和可维护性得以提升。

PHP:网络开发的关键语言 PHP:网络开发的关键语言 Apr 13, 2025 am 12:08 AM

PHP是一种广泛应用于服务器端的脚本语言,特别适合web开发。1.PHP可以嵌入HTML,处理HTTP请求和响应,支持多种数据库。2.PHP用于生成动态网页内容,处理表单数据,访问数据库等,具有强大的社区支持和开源资源。3.PHP是解释型语言,执行过程包括词法分析、语法分析、编译和执行。4.PHP可以与MySQL结合用于用户注册系统等高级应用。5.调试PHP时,可使用error_reporting()和var_dump()等函数。6.优化PHP代码可通过缓存机制、优化数据库查询和使用内置函数。7

PHP类型提示如何起作用,包括标量类型,返回类型,联合类型和无效类型? PHP类型提示如何起作用,包括标量类型,返回类型,联合类型和无效类型? Apr 17, 2025 am 12:25 AM

PHP类型提示提升代码质量和可读性。1)标量类型提示:自PHP7.0起,允许在函数参数中指定基本数据类型,如int、float等。2)返回类型提示:确保函数返回值类型的一致性。3)联合类型提示:自PHP8.0起,允许在函数参数或返回值中指定多个类型。4)可空类型提示:允许包含null值,处理可能返回空值的函数。

PHP的持久相关性:它还活着吗? PHP的持久相关性:它还活着吗? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在现代编程领域中依然占据重要地位。1)PHP的简单易学和强大社区支持使其在Web开发中广泛应用;2)其灵活性和稳定性使其在处理Web表单、数据库操作和文件处理等方面表现出色;3)PHP不断进化和优化,适用于初学者和经验丰富的开发者。

PHP和Python:代码示例和比较 PHP和Python:代码示例和比较 Apr 15, 2025 am 12:07 AM

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。

PHP与其他语言:比较 PHP与其他语言:比较 Apr 13, 2025 am 12:19 AM

PHP适合web开发,特别是在快速开发和处理动态内容方面表现出色,但不擅长数据科学和企业级应用。与Python相比,PHP在web开发中更具优势,但在数据科学领域不如Python;与Java相比,PHP在企业级应用中表现较差,但在web开发中更灵活;与JavaScript相比,PHP在后端开发中更简洁,但在前端开发中不如JavaScript。

See all articles