Que no se generen ficheros residuales de Microsoft Word

Veran, tengo la siguiente función para imprimir en Word:

public function imprimirWord(Juego $j){
    $phpWord=new \PhpOffice\PhpWord\PhpWord();
    $phpWord->getSettings()->setThemeFontLang(new Language(Language::ES_ES));
    $section=$phpWord->addSection();
    
    $text=$section->addText('Juego Nº '.$j->numero.': '.$j->nombre,array('name'=>'Arial','size' => 15,'bold' => true));
    $section->addImage($j->ruta(), array('width'=>400, 'height'=>300, 'align'=>'center'));
    $text=$section->addText("-Materiales requeridos: ".$j->materiales);
    $text=$section->addText("-Agrupación: ".$j->organizacion);
    $text=$section->addText("-Cómo se organiza el juego: ".$j->agrupacion->nombre);
    $text=$section->addText("-Desarrollo del juego: ".$j->desarrollo);
    if($j->observaciones!='*')
        $text=$section->addText("-Reglas y observaciones: ".$j->observaciones);
    if($j->variantes!='*')
        $text=$section->addText("-Variantes del juego: ".$j->variantes);
    $contenidos=$j->enlaces;
    $valor=count($contenidos);
    if($valor){
        $texto="";
        foreach($contenidos as $contenido){
            $texto.=" ".$contenido->contenido->nombre;
            $valor--;
            if($valor>1)
                $texto.=",";
            else if($valor==1)
                $texto.=" y";
            else
                $texto.=".";
        }
        $text=$section->addText("-Contenidos del juego:".$texto);
    }
    
    $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
    $deciso='Juego Nº '.$j->numero.' - '.$j->nombre.'.docx';
    $objWriter->save($deciso);
    return response()->download(public_path($deciso));
}

Gracias a ella logro crear mis ficheros en word, pero a cambio me encuentro con esto:

Se me acumulan internamente los ficheros en mi proyecto. No quiero que pase eso, por lo que quisiera saber como permitir al usuario descargarselo sin que se genere una copia en mi proyecto.

You might want to have a look at how to output a file for the browser to download, and then unlink the doc file

Unlink a file?
I know this command, but it bust be use after the word file is download.
How?
I try use this:

unlink($objWriter);

But fail and the computer show me a error message.

Más información.
Tengo este código:

$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
$deciso='Juego Nº '.$j->numero.' - '.$j->nombre.'.docx';
$objWriter->save($deciso);
unlink($deciso);
return response()->download(public_path($deciso));

Y me da esto al ejecutarlo:

Ya he logrado eliminar al documento word. Si primero lo borro y luego lo descargo ovbiamente falla todo, pero si primero hago la descarga, al usar un return ya no se borrara.
¿Como permito que el usuario se lo descargue sin el uso de return?

Algo que me han sugerido es que guarde el fichero en la carpeta /tmp, ya que esta se va “reiniciando” con el tiempo.
Cuando creo el fichero con save, el proyecto se guarda en public_html. ¿Como hago para que se guarde en la otra carpeta?

De hecho, intente esto:

$deciso='/tmp/Juego Nº '.$j->numero.' - '.$j->nombre.'.docx';
$objWriter->save($deciso);
return response()->download(public_path($deciso));

Pero me ha salido este mensaje de error:

file_exists(): open_basedir restriction in effect. File(/tmp/Juego Nº 94 - El Gusano.docx) is not within the allowed path(s): (/opt/awex-pages:/storage/ssd3/074/6581074)

Can you post the file_exists() code you use?

file_exists?
This is my actual code:

public function imprimirWord(Juego $j){
    $phpWord=new \PhpOffice\PhpWord\PhpWord();
    $phpWord->getSettings()->setThemeFontLang(new Language(Language::ES_ES));
    $section=$phpWord->addSection();
    
    $text=$section->addText('Juego Nº '.$j->numero.': '.$j->nombre, array('name'=>'Arial','size' => 15,'bold' => true));
    $section->addImage($j->ruta(), array('width'=>400, 'height'=>300, 'align'=>'center'));
    $general=array('bold'=>true);
    
    $text=$section->addText("-Materiales requeridos: ", $general);
    $text=$section->addText($j->materiales);
    
    $text=$section->addText("-Agrupación: ", $general);
    $text=$section->addText($j->organizacion);
    
    $text=$section->addText("-Cómo se organiza el juego: ", $general);
    $text=$section->addText($j->agrupacion->nombre);
    
    $text=$section->addText("-Desarrollo del juego: ", $general);
    $text=$section->addText($j->desarrollo);
    
    if($j->observaciones!='*'){
        $text=$section->addText("-Reglas y observaciones: ", $general);
        $text=$section->addText($j->observaciones);
    }
    
    if($j->variantes!='*'){
        $text=$section->addText("-Variantes del juego: ", $general);
        $text=$section->addText($j->variantes);
    }
    
    $contenidos=$j->enlaces;
    $valor=count($contenidos);
    if($valor){
        $texto="";
        foreach($contenidos as $contenido){
            $texto.=" ".$contenido->contenido->nombre;
            $valor--;
            if($valor>1)
                $texto.=",";
            else if($valor==1)
                $texto.=" y";
            else
                $texto.=".";
        }
        $text=$section->addText("-Contenidos del juego:", $general);
        $text=$section->addText($texto);
    }

    $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
    $deciso='Juego Nº '.$j->numero.' - '.$j->nombre.'.docx';
    $objWriter->save($deciso);
    return response()->download(public_path($deciso));
}

I have no idea of how to help you :confused:

@teodor @Infinity

After the user download the file, the file must be eliminate of my project.
This file is created by the command “$objWriter->save($deciso);”.
The file that allow the download is “return response()->download(public_path($deciso));”.
The command that allow delete the file is “unlink($deciso);”.
If use “unlink” before return “response()->download”, i can`t download the file.
But if I use “unlink” after return “response()->download”, it don´t work.

Remove return does the unlink work?

If write only “response()->download(public_path($deciso));” i can use unlink, but the file don’t download.

Al final, se me ha ocurrido lo siguiente:

De entrada, he creado lo siguiente en Juego.php:

public function ficheto(){
    return 'descargas/Juego Nº '.$this->numero.' - '.$this->nombre.'.docx';
}

La historia es que para emprezar he creado una carpeta “descargas”, donde a partir de ahora almacenare los ficheros Word.
El siguiente paso es hacer este cambio radical:

public function imprimirWord(Juego $j){
    $deciso=$j->ficheto();
    if(!file_exists($deciso)){
        $phpWord=new \PhpOffice\PhpWord\PhpWord();
        $phpWord->getSettings()->setThemeFontLang(new Language(Language::ES_ES));
        $section=$phpWord->addSection();
        
        $text=$section->addText('Juego Nº '.$j->numero.': '.$j->nombre, array('name'=>'Arial','size' => 15,'bold' => true));
        $section->addImage($j->ruta(), array('width'=>400, 'height'=>300, 'align'=>'center'));
        $general=array('bold'=>true);
        
        $text=$section->addText("-Materiales requeridos: ", $general);
        $text=$section->addText($j->materiales);
        
        $text=$section->addText("-Agrupación: ", $general);
        $text=$section->addText($j->organizacion);
        
        $text=$section->addText("-Cómo se organiza el juego: ", $general);
        $text=$section->addText($j->agrupacion->nombre);
        
        $text=$section->addText("-Desarrollo del juego: ", $general);
        $text=$section->addText($j->desarrollo);
        
        if($j->observaciones!='*'){
            $text=$section->addText("-Reglas y observaciones: ", $general);
            $text=$section->addText($j->observaciones);
        }
        
        if($j->variantes!='*'){
            $text=$section->addText("-Variantes del juego: ", $general);
            $text=$section->addText($j->variantes);
        }
        
        $contenidos=$j->enlaces;
        $valor=count($contenidos);
        if($valor){
            $texto="";
            foreach($contenidos as $contenido){
                $texto.=" ".$contenido->contenido->nombre;
                $valor--;
                if($valor>1)
                    $texto.=",";
                else if($valor==1)
                    $texto.=" y";
                else
                    $texto.=".";
            }
            $text=$section->addText("-Contenidos del juego:", $general);
            $text=$section->addText($texto);
        }

        $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
        $objWriter->save($deciso);
    }
    return response()->download(public_path($deciso));
}

Esto hara que en caso de que ya se haya creado el fichero, se descargue directamente para no tener que volver a crearlo otra vez.
Esto es más eficiente para el usuario al darle la posibilidad de que tarde menos tiempo en descargarse, pero me da una serie de pegas.
Hay 2 que he descubierto:
Cada vez que modifique o elimine el juego, seria recomendable eliminar el fichero, ya que ahora sera datos obsoletos.
A partir de ahora estoy obligado a que no puedan haber 2 juegos que se llamen igual, ya que eso podria causar que se descargue por error el Word de otro juego. Esto ultimo me va a obligar a hacer cambios en mi base de datos.

¿Alguien se le ocurre otras complicaciones que deba tener en cuenta?

Listo. A partir de ahora, de existir el fichero se borrara cuando el juego sea modificado o eliminado.
Ademas, a partir de ahora ya no podran existir 2 juegos con el mismo nombre.
Esto deberia solucionar todos mis problemas.

1 Like

So the problem is solved?

1 Like

Si, esto soluciona mi problema.
PD: Ya es tarde, pero resulta que esto era lo que buscaba:

return response()
  ->download($tempDoc, $deciso, $headers)
  ->deleteFileAfterSend(true);

El “deleteFileAfterSend” habria servido para eliminar el fichero tras la descarga. Ya no me sirve, pero aqui queda por si le sirve a alguien el día de mañana.