user2828442
user2828442

Reputation: 2515

How to save the image fetched from DOCX by PHP using ZipArchive

Brief description: I have a Docx file. I have done a simple code in PHP which extracts the images in that file and display it on the page.

What I want to achieve: I want that these images should be saved beside my php file with the same name and format.

My folder has sample.docx (which has images), extract.php (which extracts the images from docx) and display.php

Below is the code of extract.php

<?php    
/*Name of the document file*/
$document = 'sample.docx';

/*Function to extract images*/ 
function readZippedImages($filename) {

    /*Create a new ZIP archive object*/
    $zip = new ZipArchive;

    /*Open the received archive file*/
    if (true === $zip->open($filename)) {
        for ($i=0; $i<$zip->numFiles;$i++) {

            /*Loop via all the files to check for image files*/
            $zip_element = $zip->statIndex($i);                

            /*Check for images*/
            if(preg_match("([^\s]+(\.(?i)(jpg|jpeg|png|gif|bmp))$)",$zip_element['name'])) {    

                /*Display images if present by using display.php*/
                echo "<image src='display.php?filename=".$filename."&index=".$i."' /><hr />";

            }
        }
    }
}
readZippedImages($document);
?>

display.php

<?php
/*Tell the browser that we want to display an image*/
header('Content-Type: image/jpeg');        

/*Create a new ZIP archive object*/
$zip = new ZipArchive;

/*Open the received archive file*/
if (true === $zip->open($_GET['filename'])) {    
/*Get the content of the specified index of ZIP archive*/
echo $zip->getFromIndex($_GET['index']);
}

$zip->close();
?>

How can I do that?

Upvotes: 0

Views: 634

Answers (1)

Professor Abronsius
Professor Abronsius

Reputation: 33813

I not sure that you need to open the zip archive multiple times like this - especially when another instance is already open but I'd be tempted to try something like the following - I should stress that it is totally untested though.

Updated after testing: There is no need to use display.php if you do like this - seems to work ok on different .docx files. The data returned by $zip->getFromIndex yields the raw image data ( so I discovered )so passing that in a query string is not possible due to the length. I tried to avoid opening/closing the zip archive unnecessarily hence the approach below which adds the raw data to the output array and the image is then displayed using this base64 encoded data inline.

<?php    
    #extract.php

    $document = 'sample.docx';

    function readZippedImages($filename) {
        $paths=[];
        $zip = new ZipArchive;
        if( true === $zip->open( $filename ) ) {
            for( $i=0; $i < $zip->numFiles;$i++ ) {
                $zip_element = $zip->statIndex( $i );
                if( preg_match( "([^\s]+(\.(?i)(jpg|jpeg|png|gif|bmp))$)", $zip_element['name'] ) ) {
                    $paths[ $zip_element['name'] ]=base64_encode( $zip->getFromIndex( $i ) );
                }
            }
        }
        $zip->close();
        return $paths;
    }
    $paths=readZippedImages( $document );





    /* to display & save the images */
    foreach( $paths as $name => $data ){
        $filepath=__DIR__ . '/' . $name;
        $dirpath=pathinfo( $filepath, PATHINFO_DIRNAME );
        $ext=pathinfo( $name, PATHINFO_EXTENSION );
        if( !file_exists( $dirpath ) )mkdir( $dirpath,0777, true );
        if( !file_exists( $filepath ) )file_put_contents( $filepath, base64_decode( $data ) );

        printf('<img src="data:image/%s;base64, %s" />', $ext, $data );
    }
?>

Upvotes: 1

Related Questions