大文件数据导出(后台执行,自动生成)
2015-08-11 10:47
316 查看
阅读目录
一、前言
二、生成excel文件
三、让程序在后台执行
四、显示文件生成进度
五、下载文件
六、上线后出现的问题
七、相应的后续优化
八、后记
大家知道,excel导出数据的功能,后台几乎是必须功能,一般都是点击后,生成文件然后自动下载,
如果是数据量小的话,一下子便可请求完成,从而下载到本地;
但是,如果数据量特别大的时候,页面就必须一直在等待,直到写入excel成功,
这样便影响了后台使用者无法操作其他页面,为此,对excel导出做了以下功能优化:
excel导出分成两部分内容:生成excel文件和下载excel文件
excel的文件生成在程序后台执行,前端不必等待,可进行其他后台操作
增加下载文件页面,显示excel文件生成的进度,完成后,方可下载生成的excel文件
文件生成后,点击下载方可下载相应的文件
这里用到了table的html格式,以及相应的excel的声明
(隐约记得其他的方法用office07打开的时候好像是乱码,后面尝试用csv格式文件,可还是乱码,所以用了table的形式)
文件的开头:
$struserdata = <<<Eof
<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=utf-8" />
<style id="Classeur1_16681_Styles">
</style>
</head>
<body>
<div id="Classeur1_16681" align=center x:publishsource="Excel">
<table x:str border=1 cellpadding=0 cellspacing=0 width=100% style='border-collapse: collapse'>
Eof;
文件的结尾:
当然,文件中间就是一些tr td 标签了。
场景:
用户点击 生成excel后,跳转到下载页面,程序在后台执行,用户可不必等待生成完成,可执行其他操作;
下载页面可看到文件生成的进度以及是否可下载状态
思路:
点击 生成excel,显示下载页面 ---> show_download方法
生成excel ---> create_excel 方法
show_download方法中调用 create_excel方法,而show_download 方法中,自己用了一下命令行执行程序的方式,
利用php命令行的方式,把参数传递给 create_excel方法
public function execscript_process(){
$this->load->library('smarty');
$file_arr_str = array();
$file_arr_process = array();
$file_arr_name = array();
$file_arr = array();
$refresh_flag = 'yes';
$uid = $_REQUEST['uid'];
$url_dir = STATISTIC_EXPORT_FILE_DIR.$uid .'/';//@todo
if(!is_dir($url_dir)){
@mkdir($url_dir,0777);
}
$files = scandir($url_dir);
if(!empty($files)){
foreach ($files as $key => $value) {
if($value!='.' && $value!='..'){
if(substr($value, 0 , 5)=="flag_"){
$file_size = filesize($url_dir . $value);
if(!empty($file_size)){
$fhandle = fopen($url_dir . $value, 'rb+');
fseek($fhandle, -1, SEEK_END);
$fstr = '';
while(($c = fgetc($fhandle)) !== false) {
if($c == "\n" && $fstr) break;
$fstr = $c . $fstr;
fseek($fhandle, -2, SEEK_CUR);
}
fclose($fhandle);
$fstr = trim($fstr);
$fstr_arr_str = explode(',', $fstr);
$file_arr_process[] = 100 * number_format($fstr_arr_str[0]/$fstr_arr_str[1],2).'%';
$file_arr_name[] = substr($value,5);
}
}
}
}
foreach ($file_arr_process as $key => $value) {
if($value != '100%'){
$refresh_flag = 'no';
break;
}
}
}
$file_arr = array(
'process' => $file_arr_process,
'name' => $file_arr_name,
'refresh_flag' => $refresh_flag
);
$file_arr_json = json_encode($file_arr);
echo $file_arr_json;
}
现象描述:
当在后台点击生成文件,跳转到下载页的时候,因为下载页是显示文件进度的页面,
竟然出现有时候有刚刚点击的文件进度,有时候没有,就感觉没有生成相应的文件一样;
解决方法:
因为数据文件和进度文件都是生成在程序的某个文件夹file中,所以读取的时候都是读取的文件夹下的文件,从而判断显示进度;
后面才知道,由于后台程序有两台服务器,导致读取以及下载的时候找不到相应的文件夹,两个服务器相应的文件夹弄个共享目录就可以了
当然可以用crontab,只不过我比较懒,是在点击生成文件的时候,判断了一下文件夹中的过期文件,从而删除
当时在用命令行执行方法的时候,也参考了一下相应的资料,记录一下;
一、前言
二、生成excel文件
三、让程序在后台执行
四、显示文件生成进度
五、下载文件
六、上线后出现的问题
七、相应的后续优化
八、后记
一、前言
记录一下以前做的后台excel格式导出统计信息的功能,也是最近同事问到了相关东西,一时之间竟忘了具体的细节,因此记录一下;大家知道,excel导出数据的功能,后台几乎是必须功能,一般都是点击后,生成文件然后自动下载,
如果是数据量小的话,一下子便可请求完成,从而下载到本地;
但是,如果数据量特别大的时候,页面就必须一直在等待,直到写入excel成功,
这样便影响了后台使用者无法操作其他页面,为此,对excel导出做了以下功能优化:
excel导出分成两部分内容:生成excel文件和下载excel文件
excel的文件生成在程序后台执行,前端不必等待,可进行其他后台操作
增加下载文件页面,显示excel文件生成的进度,完成后,方可下载生成的excel文件
文件生成后,点击下载方可下载相应的文件
二、生成excel文件
生成excel文件的方法有很多,暂不一一记录,只是记录本次的方法;这里用到了table的html格式,以及相应的excel的声明
(隐约记得其他的方法用office07打开的时候好像是乱码,后面尝试用csv格式文件,可还是乱码,所以用了table的形式)
文件的开头:
$struserdata = <<<Eof
<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=utf-8" />
<style id="Classeur1_16681_Styles">
</style>
</head>
<body>
<div id="Classeur1_16681" align=center x:publishsource="Excel">
<table x:str border=1 cellpadding=0 cellspacing=0 width=100% style='border-collapse: collapse'>
Eof;
文件的结尾:
1 $struserdata = <<<Eof 2 </table> 3 </div> 4 </body> 5 </html> 6 Eof;
当然,文件中间就是一些tr td 标签了。
三、让程序在后台执行
场景:
用户点击 生成excel后,跳转到下载页面,程序在后台执行,用户可不必等待生成完成,可执行其他操作;
下载页面可看到文件生成的进度以及是否可下载状态
思路:
点击 生成excel,显示下载页面 ---> show_download方法
生成excel ---> create_excel 方法
show_download方法中调用 create_excel方法,而show_download 方法中,自己用了一下命令行执行程序的方式,
利用php命令行的方式,把参数传递给 create_excel方法
public function execscript_process(){
$this->load->library('smarty');
$file_arr_str = array();
$file_arr_process = array();
$file_arr_name = array();
$file_arr = array();
$refresh_flag = 'yes';
$uid = $_REQUEST['uid'];
$url_dir = STATISTIC_EXPORT_FILE_DIR.$uid .'/';//@todo
if(!is_dir($url_dir)){
@mkdir($url_dir,0777);
}
$files = scandir($url_dir);
if(!empty($files)){
foreach ($files as $key => $value) {
if($value!='.' && $value!='..'){
if(substr($value, 0 , 5)=="flag_"){
$file_size = filesize($url_dir . $value);
if(!empty($file_size)){
$fhandle = fopen($url_dir . $value, 'rb+');
fseek($fhandle, -1, SEEK_END);
$fstr = '';
while(($c = fgetc($fhandle)) !== false) {
if($c == "\n" && $fstr) break;
$fstr = $c . $fstr;
fseek($fhandle, -2, SEEK_CUR);
}
fclose($fhandle);
$fstr = trim($fstr);
$fstr_arr_str = explode(',', $fstr);
$file_arr_process[] = 100 * number_format($fstr_arr_str[0]/$fstr_arr_str[1],2).'%';
$file_arr_name[] = substr($value,5);
}
}
}
}
foreach ($file_arr_process as $key => $value) {
if($value != '100%'){
$refresh_flag = 'no';
break;
}
}
}
$file_arr = array(
'process' => $file_arr_process,
'name' => $file_arr_name,
'refresh_flag' => $refresh_flag
);
$file_arr_json = json_encode($file_arr);
echo $file_arr_json;
}
五、下载文件
文件的下载就好说了,既然已经都生成成功,下载的方法如下:1 public function execscript_download(){ 2 $filename = $_REQUEST['filename']; 3 $uid = $_REQUEST['uid']; 4 $file_dir = STATISTIC_EXPORT_FILE_DIR.$uid.'/'.$filename; 5 if (!file_exists($file_dir)){ 6 header("Content-type: text/html; charset=utf-8"); 7 echo "File not found!"; 8 exit; 9 } else { 10 ini_set("memory_limit","500M"); 11 header('Content-Description: File Transfer'); 12 header('Content-Type: application/octet-stream'); 13 header('Content-Disposition: attachment; filename='.basename($file_dir)); 14 header('Content-Transfer-Encoding: binary'); 15 header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT'); 16 header('Cache-Control: must-revalidate,post-check=0, pre-check=0'); 17 header('Pragma: public'); 18 header('Content-Length: ' . filesize($file_dir)); 19 readfile($file_dir); 20 } 21 22 }
六、上线后出现的问题
本地本来已经测试完毕,可上线后,却出现了奇怪的问题;现象描述:
当在后台点击生成文件,跳转到下载页的时候,因为下载页是显示文件进度的页面,
竟然出现有时候有刚刚点击的文件进度,有时候没有,就感觉没有生成相应的文件一样;
解决方法:
因为数据文件和进度文件都是生成在程序的某个文件夹file中,所以读取的时候都是读取的文件夹下的文件,从而判断显示进度;
后面才知道,由于后台程序有两台服务器,导致读取以及下载的时候找不到相应的文件夹,两个服务器相应的文件夹弄个共享目录就可以了
七、相应的后续优化
由于下载的文件多了,导致文件夹下的文件越来越多,而原来生成的文件是没有价值的,所以加了个定期删除文件的功能,只保留近七天的文件当然可以用crontab,只不过我比较懒,是在点击生成文件的时候,判断了一下文件夹中的过期文件,从而删除
1 public function execscript_process_show(){ 2 $this->load->library('smarty'); 3 $uid = $_REQUEST['uid']; 4 $url_dir = STATISTIC_EXPORT_FILE_DIR.$uid .'/';//@todo 5 if(!is_dir($url_dir)){ 6 @mkdir($url_dir,0777); 7 } 8 $files = scandir($url_dir); 9 if(!empty($files)){ 10 foreach ($files as $key => $value) { 11 if($value!='.' && $value!='..'){ 12 foreach ($files as $key => $value) { 13 if($value!='.' && $value!='..'){ 14 if(substr($value, 0 , 5)!="flag_"){ 15 $filenamedate = substr($value, 0,10); 16 $today = date('Y-m-d',time()); 17 $filenamedate = date('Y-m-d',strtotime($filenamedate)+(STATISTIC_FILE_EXPIRE_DAY-1)*24*3600); 18 if($today>$filenamedate){//文件过期 19 @unlink($url_dir . $value); 20 @unlink($url_dir . 'flag_' . $value); 21 } 22 } 23 } 24 } 25 } 26 } 27 } 28 29 $this->smarty->assign('uid',$uid); 30 $this->smarty->display('interact/statistic/execscript.tpl'); 31 }
八、后记
大文件的导出大体就是这个样子,欢迎大家吐槽,共同交流;当时在用命令行执行方法的时候,也参考了一下相应的资料,记录一下;
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[/code]
相关文章推荐
- 关于机器学习中规则与统计方法的思考
- 淘宝网页充值代码
- php5.5 + apache2.4 安装配置
- DCE中从linux sendto转换为dce的关节部分
- 省市区三级联动下拉框菜单javascript版
- Leetcode#5||Longest Palindromic Substring
- 文章标题
- 21-IO流-09-IO流(字符流-练习-复制文本文件_2)
- SDUTOJ懒虫小鑫
- Windows下搭建GCC + Eclipse + OpenOCD的ARM开发环境
- 开源领导者应该入乡随俗吗?
- git pull错误记录及解决
- Android 即时语音聊天工具 开发
- NSString 查找指定字符串出现的次数
- Codeforces Round #315 (Div. 2) A. Music
- TCPClient
- 基于libssh库实现SSH的Linux客户端程序
- 《Spring 2.0技术手册》 读书笔记七-Spring的DAO框架(3)-JDBC事务管理
- 用代码写布局
- 文本分类,数据挖掘和机器学习