Commit 055dd94f authored by Mahmoud Aglan's avatar Mahmoud Aglan

coco

parent b98c1c14
...@@ -558,7 +558,9 @@ class TutorialController extends Controller ...@@ -558,7 +558,9 @@ class TutorialController extends Controller
public function exportPdf(Request $request): Response public function exportPdf(Request $request): Response
{ {
set_time_limit(480); set_time_limit(1800);
$dlToken = $_GET['dl'] ?? '';
$screenshotsPath = realpath(__DIR__ . '/../../../../public/assets/tutorials/screenshots'); $screenshotsPath = realpath(__DIR__ . '/../../../../public/assets/tutorials/screenshots');
$viewsPath = realpath(__DIR__ . '/../Views'); $viewsPath = realpath(__DIR__ . '/../Views');
...@@ -605,6 +607,10 @@ class TutorialController extends Controller ...@@ -605,6 +607,10 @@ class TutorialController extends Controller
$pdfContent = file_get_contents($tmpOutput); $pdfContent = file_get_contents($tmpOutput);
@unlink($tmpOutput); @unlink($tmpOutput);
if ($dlToken) {
setcookie('book_download', $dlToken, time() + 120, '/');
}
$response = new Response(); $response = new Response();
return $response->html($pdfContent, 200)->withHeaders([ return $response->html($pdfContent, 200)->withHeaders([
'Content-Type' => 'application/pdf', 'Content-Type' => 'application/pdf',
...@@ -615,6 +621,10 @@ class TutorialController extends Controller ...@@ -615,6 +621,10 @@ class TutorialController extends Controller
@unlink($tmpOutput); @unlink($tmpOutput);
} }
if ($dlToken) {
setcookie('book_download', $dlToken, time() + 120, '/');
}
$response = new Response(); $response = new Response();
return $response->html($html, 200)->withHeaders([ return $response->html($html, 200)->withHeaders([
'Content-Type' => 'text/html; charset=utf-8', 'Content-Type' => 'text/html; charset=utf-8',
......
...@@ -127,14 +127,20 @@ ...@@ -127,14 +127,20 @@
<script> <script>
var exportSteps = [ var exportSteps = [
{ pct: 5, label: 'تحضير البيانات...' }, { pct: 5, label: 'تحضير البيانات...' },
{ pct: 15, label: 'تجميع شروحات العضوية...' }, { pct: 12, label: 'تجميع شروحات العضوية...' },
{ pct: 30, label: 'تجميع شروحات الأنشطة الرياضية...' }, { pct: 20, label: 'تجميع شروحات الأنشطة الرياضية...' },
{ pct: 45, label: 'تجميع شروحات الخزنة...' }, { pct: 28, label: 'تجميع شروحات الخزنة...' },
{ pct: 55, label: 'تجميع باقي الأقسام...' }, { pct: 35, label: 'تجميع باقي الأقسام...' },
{ pct: 70, label: 'تضمين لقطات الشاشة...' }, { pct: 45, label: 'تضمين لقطات الشاشة...' },
{ pct: 85, label: 'توليد ملف PDF...' }, { pct: 55, label: 'توليد ملف PDF...' },
{ pct: 92, label: 'تجهيز التحميل...' }, { pct: 65, label: 'معالجة الصفحات...' },
{ pct: 72, label: 'تنسيق المحتوى...' },
{ pct: 80, label: 'ضغط الملف...' },
{ pct: 88, label: 'المراجعة النهائية...' },
{ pct: 94, label: 'جاري الانتهاء...' },
]; ];
var stepTimer = null;
var cookieTimer = null;
function startExport() { function startExport() {
document.getElementById('beforeExport').style.display = 'none'; document.getElementById('beforeExport').style.display = 'none';
...@@ -155,42 +161,47 @@ function startExport() { ...@@ -155,42 +161,47 @@ function startExport() {
progressStep.textContent = step.label; progressStep.textContent = step.label;
stepIndex++; stepIndex++;
if (stepIndex < exportSteps.length) { if (stepIndex < exportSteps.length) {
setTimeout(animateStep, 8000); stepTimer = setTimeout(animateStep, 90000);
} }
} }
animateStep(); animateStep();
fetch('/tutorials/export-pdf') // Use hidden iframe — browsers don't timeout iframe downloads
.then(function(response) { var token = Date.now().toString();
if (!response.ok) throw new Error('HTTP ' + response.status); var iframe = document.createElement('iframe');
return response.blob(); iframe.style.display = 'none';
}) iframe.setAttribute('id', 'exportFrame');
.then(function(blob) { iframe.src = '/tutorials/export-pdf?dl=' + token;
document.body.appendChild(iframe);
// Poll for download cookie (set by server when response is sent)
cookieTimer = setInterval(function() {
if (document.cookie.indexOf('book_download=' + token) !== -1) {
clearInterval(cookieTimer);
clearTimeout(stepTimer);
// Clear the cookie
document.cookie = 'book_download=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';
progressBar.style.width = '100%'; progressBar.style.width = '100%';
progressLabel.textContent = '100%'; progressLabel.textContent = '100%';
progressStep.textContent = 'اكتمل!'; progressStep.textContent = 'اكتمل! تم التحميل ✓';
setTimeout(function() { finishExport(true); }, 1500);
var filename = 'Book-of-the-ERP.pdf'; // Clean up iframe
if (blob.type && blob.type.indexOf('html') !== -1) { var f = document.getElementById('exportFrame');
filename = 'Book-of-the-ERP.html'; if (f) setTimeout(function() { f.remove(); }, 5000);
} }
var url = window.URL.createObjectURL(blob); }, 2000);
var a = document.createElement('a');
a.href = url; // Safety timeout: 25 minutes max
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function() { setTimeout(function() {
window.URL.revokeObjectURL(url); if (document.getElementById('duringExport').style.display !== 'none') {
document.body.removeChild(a); clearInterval(cookieTimer);
}, 100); clearTimeout(stepTimer);
document.getElementById('errorMessage').textContent = 'انتهت المهلة. قد يكون الملف قد تم تحميله — تحقق من مجلد التنزيلات.';
setTimeout(function() { finishExport(true); }, 600);
})
.catch(function(err) {
document.getElementById('errorMessage').textContent = 'فشل التصدير: ' + err.message;
finishExport(false); finishExport(false);
}); var f = document.getElementById('exportFrame');
if (f) f.remove();
}
}, 1500000);
} }
function finishExport(success) { function finishExport(success) {
...@@ -208,6 +219,8 @@ function resetExport() { ...@@ -208,6 +219,8 @@ function resetExport() {
document.getElementById('afterExport').style.display = 'none'; document.getElementById('afterExport').style.display = 'none';
document.getElementById('errorExport').style.display = 'none'; document.getElementById('errorExport').style.display = 'none';
document.getElementById('progressBar').style.width = '0%'; document.getElementById('progressBar').style.width = '0%';
clearInterval(cookieTimer);
clearTimeout(stepTimer);
} }
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
DocumentRoot /var/www/html/public DocumentRoot /var/www/html/public
# Allow long-running requests (PDF generation) # Allow long-running requests (PDF generation)
TimeOut 480 TimeOut 1800
<Directory /var/www/html/public> <Directory /var/www/html/public>
Options -Indexes +FollowSymLinks Options -Indexes +FollowSymLinks
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
upload_max_filesize = 20M upload_max_filesize = 20M
post_max_size = 25M post_max_size = 25M
memory_limit = 1024M memory_limit = 1024M
max_execution_time = 480 max_execution_time = 1800
max_input_time = 240 max_input_time = 240
max_input_vars = 5000 max_input_vars = 5000
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment