실제 작업에서는 보고서를 내보내야 하는 경우가 많습니다. 내보낸 데이터의 양이 너무 많으면 시간 초과 및 메모리 오버플로 문제가 발생하는 경우가 많습니다.
해결책 1
사용 가능한 시간 제한: set_time_limit(0)이 해결되었습니다.
메모리 오버플로가 가능합니다: ini_set('memory_limit', 'custom memory').
해결책 2
최적화 프로그램은 데이터베이스나 파일을 사용하여 중간 결과를 캐시합니다.
해결책 3
Ajax를 사용하여 다중 요청, 파일 작성, 파일 다운로드 등의 효과는 위와 같습니다. (효과 사진은 gif이므로 업로드할 수 없습니다. 보려면 아래 링크를 이용하세요.)
(옵션 3) 모든 사람에게 데모 제공
디자인 아이디어
1. 요청을 100개로 분할했습니다. 요청이 성공하고 진행률 표시줄이 1%씩 진행됩니다.
2. 각 요청에는 파일에 쓴 다음 파일에 추가해야 합니다.
3. 파일 작성이 완료되면 다운로드 버튼이 표시되며, 클릭하시면 다운로드가 가능합니다.
기능점수
1. 두 가지 진행률 표시줄 스타일.
2. 제이쿼리 아약스.
3. CSV에 데이터를 씁니다.
4. 파일을 다운로드합니다.
페이지 스타일: 부트스트랩.
코드는 다음과 같습니다: <?php<br />
/**<br />
* CSV 파일 내보내기<br />
* @param 배열 $data 데이터<br />
* @param array $header_data 데이터의 첫 번째 행<br />
* @param string $file_name 파일명<br />
* @param int $type 카테고리<br />
* @return 문자열<br />
*/<br />
함수 _export_csv($data = [], $header_data = [], $file_name = '', $type = 0)<br />
{<br />
$fp = fopen($file_name, 'a+');<br />
if (($type != 1) && !empty($header_data)) {<br />
foreach ($header_data as $key => $value) {<br>
$header_data[$key] = iconv('utf-8', 'gbk', $value);<br>
}<br>
fputcsv($fp, $header_data);<br>
}<br>
$num = 0;<br>
//$limit 라인마다 너무 크지도 작지도 않게 출력 버퍼를 새로 고칩니다.<br>
$한도 = 100000;<br>
//메모리 낭비 없이 한 줄씩 데이터 가져오기<br>
$count = 개수($data);<br>
If ($count > 0) {<br>
for ($i = 0; $i < $count; $i++) {<br />
$num++;<br />
// 너무 많은 데이터로 인해 발생하는 문제를 방지하기 위해 출력 버퍼를 새로 고칩니다. <br />
If ($limit == $num) {<br />
ob_flush();<br />
플러시();<br />
$num = 0;<br />
}<br />
$row = $data[$i];<br />
foreach ($row as $key => $value) {<br> $row[$key] = iconv('utf-8', 'gbk', $value);<br>
}<br>
fputcsv($fp, $row);<br>
}<br>
}<br>
fclose($fp);<br>
}<br>
<br>
/**<br>
* 파일 다운로드<br>
* @param string $file_url 파일주소<br>
* @return 문자열<br>
*/<br>
함수 _download_file ($file_url = '')<br>
{<br>
if (!isset($file_url) || trim($file_url)=='') {<br>
die('파일 URL이 비어 있습니다.');<br>
}<br>
if (!file_exists($file_url)) {<br>
die('파일이 존재하지 않습니다.');<br>
}<br>
$file_name = 'down_'.date('YmdHis', time());<br>
$file_type = fopen($file_url,'r'); //打开文件<br>
//输入文件标签<br>
header("콘텐츠 유형: application/octet-stream");<br>
header("허용 범위: 바이트");<br>
header("Accept-Length: ".filesize($file_url));<br>
header("콘텐츠 처리: 첨부 파일; filename=".$file_name);<br>
//출문件内容<br>
echo fread($file_type, filesize($file_url));<br>
fclose($file_type);<br>
}<br>
<br>
//以后是逻辑代码,大家可以根据自己的需求进行编写。<br>
$path = '문서의 위치'; //경로 是存放文件的绝对地址。<br>
if (isset($_POST['start'])) {<br>
//每一个单独的请求,要保证文件name是唯一的,因为后face要继续进行追加。<br>
$file_name = 'demo.csv';<br>
//获取数据,根据自己的业务逻辑,去数据库获取数据。<br>
$data = [];<br>
$header_data = ['执行时间', '随机数']; //首行数据,表头<br>
//模拟数据如下:<br>
for($i=0; $i<=100; $i++) {<br />
$data[$i]['time'] = date('Y-m-d H:i:s', time());<br />
$data[$i]['num'] = mt_rand(1000,9999);<br />
}<br />
$type = ($_POST['start'] != '0') ? 1 : 0 ;<br />
//开始将数据写入到文件中<br />
_export_csv($data, $header_data, $path.$file_name, $type);<br />
//假设第100次 写入完毕,那么就可以进行下载文件啦。<br />
//可以先获取需要导出的总量,然后根据实际情况进行拆分数据,每次获取成功,进度条会显示进度。<br />
if ($_POST['start'] == 100) {<br />
die(json_encode(['code' => 'ok', 'file_path' => '/index.php?op=down&f='.$file_name]));<br>
} else {<br>
die(json_encode(['code' => 'no']));<br>
}<br>
}<br>
<br>
//简单的导出逻辑,可根据实际情况,进行开发。<br>
if (($_GET['op'] == 'down') && !empty($_GET['f'])) {<br>
_download_file($path.$_GET['f']);<br>
exit;<br>
}<br>
?><br>
<!DOCTYPE html><br>
<html lang="zh-CN"><br>
<head><br>
<meta charset="utf-8"><br>
<meta http-equiv="X-UA-Compatible" content="IE=edge"><br>
<meta name="viewport" content="width=device-width, initial-scale=1"><br>
<meta name="description" content="Demo"><br>
<meta name="keywords" content=""><br>
<!-- 新 Bootstrap 核心 CSS 文件 --><br>
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"><br>
<!-- jQuery --><br>
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script><br>
<!-- Title --><br>
<title>Demo</title><br>
</head><br>
<body><br>
<div class="container"><br>
<div class="row"><br>
<div class="col-lg-12" style="margin-top:20px"><br>
<a id="export_file" href="javascript:void(0);" class="btn btn-primary btn-lg active" role="button">导出CSV文件</a><br>
<a id="download_file" style="display:none;" href="javascript:void(0);" class="btn btn-default btn-lg active" role="button">下载文件</a><br>
</div><br>
</div><br>
<br>
<div id="process_one" class="row" style="display:none"><br>
<div class="col-lg-12" style="margin-top:20px"><br>
<div class="progress"><br>
<div id="progress-bar-one" class="progress-bar progress-bar-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width: 0%"><br>
</div><br>
</div><br>
</div><br>
</div><br>
<br>
<div id="process_two" class="row" style="display:none"><br>
<div class="col-lg-12" style="margin-top:20px"><br>
<div class="progress"><br>
<div id="progress-bar-two" class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"><br>
60%<br>
</div><br>
</div><br>
</div><br>
</div><br>
</div><br>
<br>
$(document).ready(function () {<br>
//CSV 파일 내보내기<br>
$("#export_file").click(function(){<br>
_get_data(0);<br>
});<br>
<br>
// 데이터를 얻는 방법 >
함수 _get_data(시작)<br>
{<br>
$.ajax({<br>
유형: "POST",<br>
URL: 'Index.php', <br>
데이터: {<br>
'시작' : 시작<br>
},<br>
비동기: 사실,<br>
데이터 유형: "json",<br>
beforeSend: 함수 () {<br>
$("#download_file").css('display', 'none');<br>
$("#process_one").show();<br>
~ ~
성공: 함수(결과) {<br>
If (result.code == 'ok') {<br>
$("#download_file").attr("href", result.file_path);<br>
$("#process_one").css('표시', '없음');<br>
$("#process_two").css('display', 'none');<br>
} 그렇지 않으면 {<s> 시작 ++;<br>
_get_data(시작);<br>
$("#progress-bar-one").css("width", start+'%');<br>
$("#progress-bar-two").css("width", start+'%');<br>
$("#progress-bar-two").html(start+'%');<br>
}<br>
},<br>
오류: 함수() {<br>
Alert("서버 오류~");<br>
}<br>
});<br>
}<br>
});<br>
<br>
</본문><br>
</s>