2017-09-05 69 views
0

我通过IMAP连接从邮箱获取XLSX附件,因此我可以使用PHPExcel将这些电子表格转换为PHP数组数据,但是当我加载文件并将其转换为数组时,数组为空。如何使用PHPExcel读取XLSX邮件附件文件?

这是从符合条件的邮件获取附件功能:

public function getEmailAttachments($criteria){ 
    $emails = imap_search($this->inbox, $criteria); 
    $email_attachments = []; 
    if($emails) { 
    rsort($emails); 
    foreach ($emails as $email_number) { 
     $attachments = []; 
     //get Email structure 
     $structure = imap_fetchstructure($this->inbox, $email_number); 
     /* if any attachments found... */ 
     if(isset($structure->parts) && count($structure->parts)) 
     { 
      for($i = 0; $i < count($structure->parts); $i++) 
      { 
       $attachments[$i] = array(
        'is_attachment' => false, 
        'filename' => '', 
        'name' => '', 
        'attachment' => '' 
      ); 

       if($structure->parts[$i]->ifdparameters) 
       { 
        foreach($structure->parts[$i]->dparameters as $object) 
        { 
         if(strtolower($object->attribute) == 'filename') 
         { 
          $attachments[$i]['is_attachment'] = true; 
          $attachments[$i]['filename'] = $object->value; 
         } 
        } 
       } 

       if($structure->parts[$i]->ifparameters) 
       { 
        foreach($structure->parts[$i]->parameters as $object) 
        { 
         if(strtolower($object->attribute) == 'name') 
         { 
          $attachments[$i]['is_attachment'] = true; 
          $attachments[$i]['name'] = $object->value; 
         } 
        } 
       } 

       if($attachments[$i]['is_attachment']) 
       { 
        $attachments[$i]['attachment'] = imap_fetchbody($this->inbox, $email_number, $i+1); 
        /* 3 = BASE64 encoding */ 
        if($structure->parts[$i]->encoding == 3) 
        { 
         $attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']); 
        } 
        /* 4 = QUOTED-PRINTABLE encoding */ 
        elseif($structure->parts[$i]->encoding == 4) 
        { 
         $attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']); 
        } 
       } 
      } 
     } 
     $email_attachments = array_merge($email_attachments, array_filter($attachments, function($attachment){return $attachment['is_attachment'] == 1;})); 
    } 
    } 
    imap_close($this->inbox); 
    return $email_attachments; 
} 

那么这就是XLSX文件写入到服务器,并加载它们与PHPExcel将它们转换为数组数据的功能:

public function getEmailReports(){ 
    $this->loadPhpExcel(); 
    $attachments = parent::getEmailAttachments('FROM "[email protected]"'); 
    //iterate through each attachment and save it 
    foreach($attachments as $attachment){ 
    $filename = $attachment['name']; 
    if(empty($filename)) $filename = $attachment['filename']; 
    $folder = "data/excel"; 
    $file_path = "./". $folder ."/". time() . "-" . $filename; 
    $fp = fopen($file_path, "w"); 
    fwrite($fp, $attachment['attachment']); 
    $excelReader = PHPExcel_IOFactory::createReaderForFile($file_path); 
    $excelObj = $excelReader->load($file_path); 
    foreach ($excelObj->getWorksheetIterator() as $worksheet) { 
     $worksheets[$worksheet->getTitle()] = $worksheet->toArray(); 
    } 
    fclose($fp); 
    print_r($worksheets); //ARRAY IS EMPTY HERE 
    //unlink($file_path); 
    } 
} 
+0

您测试过这个功能有多少? – rtfm

+0

@rtfm XLSX文件正在成功写入服务器,不起作用的部分是从服务器加载XLSX文件并将其转换为阵列时 –

+0

没有显示错误?没有写入日志? –

回答

1

我打开了XLSX用WinRAR文件,并发现该XL/worbooks.xml文件有一个 “S” 命名空间:

<?xml version="1.0"?> 
<s:workbook 
xmlns:s="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> 
<s:workbookPr/> 
<s:bookViews> 
<s:workbookView activeTab="0"/> 
</s:bookViews> 
<s:sheets> 
<s:sheet r:id="rId1" sheetId="1" name="Sheet1"/> 
<s:sheet r:id="rId2" sheetId="2" name="Sheet2"/> 
<s:sheet r:id="rId3" sheetId="3" name="Sheet3"/> 
<s:sheet r:id="rId4" sheetId="4" name="Sheet4"/> 
</s:sheets> 
<s:definedNames/> 
<s:calcPr fullCalcOnLoad="1" calcId="124519"/> 
</s:workbook> 

然后我发现PHPExcel GitHub库这个问题https://github.com/PHPOffice/PHPExcel/issues/571

所以我所做的就是创建PHPExcel_Reader_Excel2007扩展类中删除“的”命名空间

<?php 
class PHPExcel_Reader_Excel2007_XNamespace extends 
PHPExcel_Reader_Excel2007 
{ 

public function securityScan($xml) 
{ 
    $xml = parent::securityScan($xml); 
    return str_replace(['<s:', '</s:'], ['<', '</'], $xml); 
} 

} 

终于取代这个:

$excelReader = PHPExcel_IOFactory::createReaderForFile($file_path); 

此:

$excelReader = new PHPExcel_Reader_Excel2007_XNamespace();