我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成_PHP教程
我所经历的大文件数据导出(后台执行,自动生成),数据导出自动生成
一、前言
记录一下以前做的后台excel格式导出统计信息的功能,也是最近同事问到了相关东西,一时之间竟忘了具体的细节,因此记录一下;
大家知道,excel导出数据的功能,后台几乎是必须功能,一般都是点击后,生成文件然后自动下载,
如果是数据量小的话,一下子便可请求完成,从而下载到本地;
但是,如果数据量特别大的时候,页面就必须一直在等待,直到写入excel成功,
这样便影响了后台使用者无法操作其他页面,为此,对excel导出做了以下功能优化:
二、生成excel文件
生成excel文件的方法有很多,暂不一一记录,只是记录本次的方法;
这里用到了table的html格式,以及相应的excel的声明
(隐约记得其他的方法用office07打开的时候好像是乱码,后面尝试用csv格式文件,可还是乱码,所以用了table的形式)
文件的开头:

当然,文件中间就是一些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;
思路:
查看文件的进度方法:

五、下载文件
文件的下载就好说了,既然已经都生成成功,下载的方法如下:
<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>

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

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

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

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

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

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

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

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

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