Ask Your Question
0

Can't open pptx created by PHP (windows only)

asked 2018-10-26 09:43:53 +0200

MrEvers gravatar image

updated 2018-10-26 10:50:56 +0200

I'm developing an API in PHP that unzips a pptx file, alters a few images and some xml, then re-zips the file.

When the program runs on a (Linux) server, I have no problem opening the altered file with LibreOffice Impress. Locally I use Windows 10, and if I manually do the changes that my code does, I also have no problems. But if the file is altered by my code locally (using Apache via MAMP), Impress will claim the file is broken and can't be fixed. Office PowerPoint will open it without problems or mentions of any error.

The only reason I can think of is perhaps the way the file is stored on Windows when it is programmatically created.

=======================

Sample code (pptx to zip, extracting, re-archiving an then zip to pptx)

    $presentationFile = 'demo.pptx';
    $presArchive = 'demo.zip';

    //turn into .zip
    copy($presentationFile, $presArchive);
    unlink($presentationFile);

    //extract .zip
    $zipArchive = new \ZipArchive;
    $zipArchive->open($presArchive);
    $extractDir = 'demo';
    $zipArchive->extractTo($extractDir);
    $zipArchive->close();

    //delete zip
    unlink($presArchive);

    //archive again
    $rootPath = realpath($extractDir); //Get real path for our folder
    $zip = new \ZipArchive(); // Initialize archive object
    $zip->open($presArchive, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
    $files = new \RecursiveIteratorIterator( // Create recursive directory iterator
        new \RecursiveDirectoryIterator($rootPath),
        \RecursiveIteratorIterator::LEAVES_ONLY
    );
    foreach ($files as $name => $file){
        if (!$file->isDir()){ // Skip directories (they would be added automatically)
            // Get real and relative path for current file
            $filePath = $file->getRealPath();
            $relativePath = substr($filePath, strlen($rootPath) + 1);
            // Add current file to archive
            $zip->addFile($filePath, $relativePath);
        }
    }
    $zip->close();

    //turn back into .pptx
    copy($presArchive, $presentationFile);
    unlink($presArchive);

locally created file: https://www.dropbox.com/s/v9ehwcq1w3i...

server created file: https://www.dropbox.com/s/tqpshib93p8...

edit retag flag offensive close merge delete

Comments

a sample file would help

Mike Kaganski gravatar imageMike Kaganski ( 2018-10-26 09:52:52 +0200 )edit

@mike-kaganski I added some sample code and a sample file (on dropbox)

MrEvers gravatar imageMrEvers ( 2018-10-26 10:19:08 +0200 )edit

Thanks; and could you please attach the same pptx generated on linux?

Mike Kaganski gravatar imageMike Kaganski ( 2018-10-26 10:26:38 +0200 )edit

file has been added

MrEvers gravatar imageMrEvers ( 2018-10-26 10:51:20 +0200 )edit

1 Answer

Sort by » oldest newest most voted
0

answered 2018-10-26 10:53:09 +0200

updated 2018-10-26 11:03:15 +0200

Aha, the problem found - this is the deficiency (?) of our zip code (need to consult documentation if that's allowed; MS seems to handle it) - the filenames in the package use backslashes (\) instead of / which are used normally (MS Office also writes /!)

EDIT:

pkware appnote 6.2.0 (the normative document defining the package format used in both OOXML and ODF specifications) states this:

  file name: (Variable)

      The name of the file, with optional relative path.
      The path stored should not contain a drive or
      device letter, or a leading slash.  All slashes
      should be forward slashes '/' as opposed to
      backwards slashes '\' for compatibility with Amiga
      and Unix file systems etc.

So, the forward slashes are required in the ZIP file format (although possibly we should relax that a bit, because back-slashes don't cause problems with e.g. 7-Zip, or InfoZip).

On the other hand, why should we try to handle invalid input, when the conformant implementations all write the proper names into packages?

edit flag offensive delete link more

Comments

This works. I've added a few lines of code to clean the backslashes to forward slashes. Thank you so much, You wouldn't believe how long I've been looking for an answer.

MrEvers gravatar imageMrEvers ( 2018-10-26 11:35:47 +0200 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2018-10-26 09:43:53 +0200

Seen: 72 times

Last updated: Oct 26 '18