John Hebert Trindade Posted July 8, 2026 at 10:20 PM Report #635836 Posted July 8, 2026 at 10:20 PM Boa noite a todos, tenho um projeto em PHP com estrutura MVC que esta trabalhar, estou criando um documento do word através do php, nos browser (Chrome, Edge, firefox, opera) o download é feito naturalmente e o documento é criado. No safari diz que "Não foi possível criar o ficheiro" e o mesmo esta com o tamanho zero. não sei se estou a colocar a duvida no local certo, e caso não esteja pesso imensa desculpa. mas se alguém conseguir ajudar me agradeço. Por se tratar de um codigo muito extenso irei colocar apenas a parte que gera o documento, caso seja necessário adiciono o restante. private function generateDocx(array $dados): void { // Define o caminho base dinamicamente $basePath = $_SERVER['DOCUMENT_ROOT'] . '/app/adms/assets/'; while (ob_get_level()) { ob_end_clean(); } $nomeArquivo = 'cartaz_' . $this->id . '.docx'; $pastaTmp = $_SERVER['DOCUMENT_ROOT'] . '/app/adms/assets/tmp/tmpWord/'; $caminhoCompleto = $pastaTmp . $nomeArquivo; $phpWord = new PhpWord(); // --- PRIMEIRA PÁGINA (MANTIDA ORIGINAL) --- $section = $phpWord->addSection([ 'marginLeft' => 720, 'marginRight' => 720, 'marginBottom' => 1440 ]); $header = $section->addHeader(); $moldura = $basePath . 'images/moldura.png'; if (file_exists($moldura)) { $header->addImage($moldura, [ 'width' => 600, 'height' => 840, 'positioning' => 'absolute', 'posHorizontalRel' => 'page', 'posVerticalRel' => 'page', 'wrappingStyle' => 'behind', ]); } $section->addTextBreak(3); $caminhoFoto = $basePath . 'images/funerais/' . $dados[0]['processo'] . '/' . $dados[0]['image']; if (file_exists($caminhoFoto)) { $img = imagecreatefromjpeg($caminhoFoto); $origW = imagesx($img); $origH = imagesy($img); $wFixo = 2448; $hFixo = 3264; $bordaGrossa = 60; $espaco = 20; $bordaFina = 12; $totalBorder = $bordaGrossa + $espaco + $bordaFina; $canvasW = $wFixo + ($totalBorder * 2); $canvasH = $hFixo + ($totalBorder * 2); $canvas = imagecreatetruecolor($canvasW, $canvasH); $ouroVelho = imagecolorallocate($canvas, 197, 160, 89); $fundo = imagecolorallocate($canvas, 255, 255, 255); imagefill($canvas, 0, 0, $ouroVelho); imagefilledrectangle($canvas, $bordaGrossa, $bordaGrossa, $canvasW - $bordaGrossa - 1, $canvasH - $bordaGrossa - 1, $fundo); $inicioFina = $bordaGrossa + $espaco; imagefilledrectangle($canvas, $inicioFina, $inicioFina, $canvasW - $inicioFina - 1, $canvasH - $inicioFina - 1, $ouroVelho); $offset = $totalBorder; imagecopyresampled($canvas, $img, $offset, $offset, 0, 0, $wFixo, $hFixo, $origW, $origH); $caminhoTemp = $pastaTmp . 'foto_final_' . $this->id . '.jpg'; imagejpeg($canvas, $caminhoTemp); imagedestroy($canvas); imagedestroy($img); $section->addImage($caminhoTemp, ['width' => 140, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); } $section->addText(($dados[0]['name_genero'] == 'M' ? 'Ex.mo Sr. ' : 'Ex.ma Sra. D. ') . ($dados[0]['name_falecido'] ?? ''), ['name' => 'Baguet Script', 'size' => 14], ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section->addTextBreak(2); $fontStyle = ['name' => 'Baguet Script', 'size' => 16]; $paragraphStyle = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::BOTH, 'indentation' => ['left' => 850, 'right' => 680], 'spaceAfter' => 200]; $meses = ["janeiro", "fevereiro", "março", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"]; $formatarData = function($dataRaw) use ($meses) { if (empty($dataRaw)) return "N/A"; $d = explode('-', trim($dataRaw)); return (count($d) == 3) ? (int)$d[2] . " de " . $meses[(int)$d[1]-1] . " de " . $d[0] : "N/A"; }; $section->addText('O Velório realizar-se-á na ' . ($dados[0]['name_local_saida'] ?? 'N/A'), $fontStyle, $paragraphStyle); $section->addTextBreak(2); $section->addText('Celebração dia ' . $formatarData($dados[0]['data_missa'] ?? '') . ' pelas ' . substr($dados[0]['hora_missa'] ?? 'N/A', 0, 5), $fontStyle, $paragraphStyle); $section->addTextBreak(2); $section->addText('Funeral dia ' . $formatarData($dados[0]['data_funeral'] ?? '') . ' pelas ' . substr($dados[0]['hora_funeral'] ?? 'N/A', 0, 5) . ', sendo ' . ($dados[0]['name_tipo_servico'] ?? 'N/A') . ' no ' . ($dados[0]['name_cemiterio'] ?? 'N/A'), $fontStyle, $paragraphStyle); $footer = $section->addFooter(); $table = $footer->addTable(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $table->addRow(1350); $table->addCell(200); $cellQr = $table->addCell(2500); $cellQr->addImage($basePath . 'images/qrgoogle.png', ['width' => 50, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $cellQr->addText('Avalia-nos no Google! Sua estrela faz a DIFERENÇA. Obrigado!', ['name' => 'Arial', 'size' => 7], ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $table->addCell(550); $cellLogo = $table->addCell(2800); $cellLogo->addImage($basePath . 'images/logo/logo.png', ['width' => 110, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $table->addCell(2900); $table->addRow(300); // --- SEGUNDA PÁGINA --- $section2 = $phpWord->addSection([ 'breakType' => 'nextPage', 'marginLeft' => 720, 'marginRight' => 720, 'marginBottom' => 1440 ]); $section2->addText('Condolências', ['name' => 'Baguet Script', 'size' => 22, 'color' => 'C5A059', 'bold' => true], ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section2->addText(($dados[0]['name_genero'] == 'M' ? 'Ex.mo Sr. ' : 'Ex.ma Sra. D. ') . ($dados[0]['name_falecido'] ?? ''), ['name' => 'Baguet Script', 'size' => 14], ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section2->addTextBreak(1); $table2 = $section2->addTable(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $table2->addRow(); $tStyle = ['name' => 'Baguet Script', 'size' => 14, 'bold' => true]; $dStyle = ['name' => 'Baguet Script', 'size' => 10.5]; // Célula 1: Velório $c1 = $table2->addCell(3000); $c1->addText("Velório", $tStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $dStyle = ['name' => 'Baguet Script', 'size' => 10.5]; $c1->addText($formatarData($dados[0]['data_velorio'] ?? ''), $dStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $c1->addText(substr($dados[0]['hora_velorio'] ?? '', 0, 5) . " " . ($dados[0]['name_local_saida'] ?? ''), $dStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); // Célula 2: Celebração $c2 = $table2->addCell(3000); $c2->addText("Celebração", $tStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $c2->addText($formatarData($dados[0]['data_missa'] ?? ''), $dStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $c2->addText(substr($dados[0]['hora_missa'] ?? '', 0, 5), $dStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); // Célula 3: Funeral $c3 = $table2->addCell(3000); $c3->addText("Funeral", $tStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $c3->addText($formatarData($dados[0]['data_funeral'] ?? ''), $dStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $c3->addText(substr($dados[0]['hora_funeral'] ?? '', 0, 5) . " " . ($dados[0]['name_cemiterio'] ?? ''), $dStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); // --- 5 QUADROS COM ESPAÇAMENTO --- $section2->addTextBreak(1); $tableQuadros = $section2->addTable(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $bordaEstilo = ['borderSize' => 6, 'borderColor' => 'C5A059']; $semBorda = ['borderStyle' => 'none', 'borderSize' => 0]; for ($i = 0; $i < 5; $i++) { $tableQuadros->addRow(1300); // Quadro maior $tableQuadros->addCell(9000, $bordaEstilo); // Adiciona linha de espaçamento invisível se não for o último if ($i < 4) { $tableQuadros->addRow(450); // 0.8cm aproximadamente $tableQuadros->addCell(9000, $semBorda); } } // Rodapé da Segunda Página (duas linhas) $footer2 = $section2->addFooter(); $tableF2 = $footer2->addTable(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $tableF2->addRow(); $tableF2->addCell(9000)->addImage($basePath . 'images/logo/logo.png', ['width' => 110, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $tableF2->addRow(); $tableF2->addCell(9000); $objWriter = IOFactory::createWriter($phpWord, 'Word2007'); $objWriter->save($caminhoCompleto); if (file_exists($caminhoCompleto)) { // Limpa qualquer buffer existente e desativa o output buffering para este download if (ob_get_level()) ob_end_clean(); // Cabeçalhos essenciais para forçar o Safari a aceitar o fluxo header('Content-Description: File Transfer'); header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document'); header('Content-Disposition: attachment; filename="' . basename($caminhoCompleto) . '"'); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: no-cache, no-store, must-revalidate'); header('Pragma: no-cache'); header('Content-Length: ' . filesize($caminhoCompleto)); // Envio em pedaços (ideal para evitar timeout ou erro de leitura do macOS) $handle = fopen($caminhoCompleto, 'rb'); while (!feof($handle)) { echo fread($handle, 8192); flush(); // Força a descarga para o buffer do navegador } fclose($handle); exit; } }
JakeBass Posted July 9, 2026 at 01:17 PM Report #635837 Posted July 9, 2026 at 01:17 PM O download é efetuado via Javascript (fetch, axios, AJAX) ou por navegação direta?
John Hebert Trindade Posted July 9, 2026 at 03:25 PM Author Report #635838 Posted July 9, 2026 at 03:25 PM Por navegação directa.
Solution John Hebert Trindade Posted July 9, 2026 at 08:23 PM Author Solution Report #635839 Posted July 9, 2026 at 08:23 PM Já esta resolvido, fui fazer o download de um programa e aconteceu o mesmo. Então fui ver e tinha uma actualização do safari por favor. Após actualizar já funcionou normalmente.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now