Merge pull request #152 from box/proper_mime_type_detection

Proper mime type detection for XLSX files
This commit is contained in:
Adrien Loison 2015-12-05 00:30:28 -08:00
commit 44d72d8245
2 changed files with 45 additions and 1 deletions

View File

@ -11,6 +11,7 @@ namespace Box\Spout\Writer\Common\Helper;
class ZipHelper
{
const ZIP_EXTENSION = '.zip';
const CONTENT_TYPES_XML_FILE_NAME = '[Content_Types].xml';
/**
* Zips the root folder and streams the contents of the zip into the given stream
@ -61,7 +62,12 @@ class ZipHelper
$folderRealPath = $this->getNormalizedRealPath($folderPath) . '/';
$itemIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($folderPath, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
foreach ($itemIterator as $itemInfo) {
// In order to have the file's mime type detected properly, items need to be
// sorted in a particular order...
$itemsInfo = iterator_to_array($itemIterator);
usort($itemsInfo, [$this, 'sortItemsForCorrectMimeTypeDetection']);
foreach ($itemsInfo as $itemInfo) {
$itemRealPath = $this->getNormalizedRealPath($itemInfo->getPathname());
$itemLocalPath = str_replace($folderRealPath, '', $itemRealPath);
@ -73,6 +79,29 @@ class ZipHelper
}
}
/**
* On order to have the file's mime type detected properly, files need to be added
* to the zip file in a particular order.
* [Content_Types].xml and files located in "xl" folder should be zipped first.
*
* @param \SplFileInfo $itemInfo1 First item to compare
* @param \SplFileInfo $itemInfo2 Second item to compare
* @return int
*/
protected function sortItemsForCorrectMimeTypeDetection($itemInfo1, $itemInfo2)
{
// Have the "[Content_Types].xml" file be first
if ($itemInfo1->getFilename() === self::CONTENT_TYPES_XML_FILE_NAME) {
return -1;
} else if ($itemInfo2->getFilename() === self::CONTENT_TYPES_XML_FILE_NAME) {
return 1;
} else {
// Then make sure the files in the "xl" folder will go next
// by sorting items in reverse alphabetical order
return strcmp($itemInfo2->getRealPath(), $itemInfo1->getRealPath());
}
}
/**
* Returns canonicalized absolute pathname, containing only forward slashes.
*

View File

@ -385,6 +385,21 @@ class WriterTest extends \PHPUnit_Framework_TestCase
$this->assertInlineDataWasWrittenToSheet($fileName, 1, 'control's _x0015_ "character"');
}
/**
* @return void
*/
public function testGeneratedFileShouldHaveTheCorrectMimeType()
{
$fileName = 'test_mime_type.xlsx';
$resourcePath = $this->getGeneratedResourcePath($fileName);
$dataRows = [['foo']];
$this->writeToXLSXFile($dataRows, $fileName);
$finfo = new \finfo(FILEINFO_MIME_TYPE);
$this->assertEquals('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', $finfo->file($resourcePath));
}
/**
* @param array $allRows
* @param string $fileName