问题描述
我正在开发一项功能,允许用户上传文件(.csv、.xls 或 .xlsx)。该文件有一列包含电子邮件,然后我使用 SHA-256 将该电子邮件散列到另一列,最后导出文件。这是示例 .csv 文件:
- 输入文件:
abc@gmail.com
xyz@gmail.com
"abc@gmail.com","48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08"
"xyz@gmail.com","32e19a491662fd86de7d3806b1199b76f0ee44e928d3475f05b0c8a59912c097"
这是我的代码,我使用 PHPoffice/PHPspreadsheet 来读/写:
<?PHP
namespace ApiBundle\Controller;
use PHPOffice\PHPSpreadsheet\Reader\Xls as ReaderXls;
use PHPOffice\PHPSpreadsheet\Writer\Xls as WriterXls;
use PHPOffice\PHPSpreadsheet\Reader\Csv as ReaderCsv;
use PHPOffice\PHPSpreadsheet\Writer\Csv as WriterCsv;
use PHPOffice\PHPSpreadsheet\Spreadsheet;
use App\Requests\HashGenerator\HashGeneratorRequest;
use PHPOffice\PHPSpreadsheet\Writer\Xlsx as WriterXlsx;
use PHPOffice\PHPSpreadsheet\Reader\Xlsx as ReaderXlsx;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use App\Controller\BaseController;
/**
* Class HashGeneratorController
* @package ApiBundle\Controller
*/
class HashGeneratorController extends BaseController
{
public const MIME_TYPES = [
'xls' => 'application/vnd.ms-excel','xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet','csv' => 'text/csv','txt' => 'text/plain'
];
/**
* @Route("/hash-generator",name="hash_generator",methods={"POST"})
* @param Request $request
* @param HashGeneratorRequest $hashGeneratorRequest
* @return Response
* @throws \PHPOffice\PHPSpreadsheet\Exception
* @throws \PHPOffice\PHPSpreadsheet\Reader\Exception
* @throws \PHPOffice\PHPSpreadsheet\Writer\Exception
* @throws \App\Exceptions\ValidationFailedException
*/
public function processHash(Request $request,HashGeneratorRequest $hashGeneratorRequest)
{
$hashGeneratorRequest->setFileData($request);
$this->validate($hashGeneratorRequest);
/** @var UploadedFile $file */
$file = $hashGeneratorRequest->getFile();
$rows = $this->readFile($file);
if ($rows === false) {
return $this->responseErrorjson([],'Cannot read file');
}
$emailHashArr = [];
foreach ($rows as $row) {
$emailHashArr[] = [$row[0],hash('sha256',$row[0])];
}
$result = $this->writeFile($emailHashArr,$file,true);
if ($result === false) {
return $this->responseErrorjson([],'Cannot write file');
}
return $result;
}
public function getExportFileName($fileType,$ext = 'csv')
{
$fileName = uniqid() . "-$fileType";
// get full fileName - Default format is ".xls"
return $fileName . '.' . $ext;
}
/**
* @param UploadedFile $file
* @return array|bool
* @throws \PHPOffice\PHPSpreadsheet\Exception
* @throws \PHPOffice\PHPSpreadsheet\Reader\Exception
*/
public function readFile($file)
{
switch ($file->getClientMimeType()) {
case self::MIME_TYPES['xlsx'] :
{
$reader = new ReaderXlsx();
break;
}
case self::MIME_TYPES['xls'] :
{
$reader = new ReaderXls();
break;
}
case self::MIME_TYPES['csv'] :
case self::MIME_TYPES['txt'] :
{
$reader = new ReaderCsv();
break;
}
default: {
$reader = null;
break;
}
}
if ($reader === null) {
return false;
}
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load($file->getPathname());
$worksheet = $spreadsheet->getActiveSheet();
$rows = [];
foreach ($worksheet->getRowIterator() AS $row) {
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(true); // False if This loops through all cells,$cells = [];
foreach ($cellIterator as $cell) {
$cells[] = $cell->getValue();
}
$rows[] = $cells;
}
return $rows;
}
/**
* @param array $emailHashArr
* @param UploadedFile $file
* @param string $default
* @return bool|Response
* @throws \PHPOffice\PHPSpreadsheet\Exception
* @throws \PHPOffice\PHPSpreadsheet\Writer\Exception
*/
public function writeFile($emailHashArr,$default = false)
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// Increase row cursor after header write
$sheet->fromArray($emailHashArr,null,'A1',true);
// default export .csv file
if ($default === true) {
$writer = new WriterCsv($spreadsheet);
$ext = 'csv';
}
else {
switch ($file->getClientMimeType()) {
case self::MIME_TYPES['xlsx'] :
{
$writer = new WriterXlsx($spreadsheet);
$ext = 'xlsx';
break;
}
case self::MIME_TYPES['xls'] :
{
$writer = new WriterXls($spreadsheet);
$ext = 'xls';
break;
}
case self::MIME_TYPES['csv'] :
case self::MIME_TYPES['txt'] :
{
$writer = new WriterCsv($spreadsheet);
$ext = 'csv';
break;
}
default: {
$writer = null;
break;
}
}
}
if ($writer === null) {
return false;
}
$tmp = 'tmp.' . $ext;
$writer->save($tmp);
$response = new Response(file_get_contents($tmp));
$fs = new Filesystem();
$fs->remove($tmp);
$fileName = $this->getExportFileName('email_hash',$ext);
$response->headers->set('Content-disposition','attachment; filename="' . $fileName . '"');
if ($default === true) {
$response->headers->set('Content-Type','text/csv');
}
return $response;
}
}
<?PHP
namespace App\Requests\HashGenerator;
use App\Requests\PostRequest;
use App\Requests\CreateRequestInterface;
use Symfony\Component\Validator\Constraints as Assert;
class HashGeneratorRequest extends PostRequest implements CreateRequestInterface
{
/**
* @Assert\NotBlank
* @Assert\File(
* maxSize = "5M",* mimeTypes = {
* "application/vnd.ms-excel",* "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",* "text/csv",* "text/plain",* },* mimeTypesMessage = "We are very sorry,but this file type is not supported. Please upload .xls,.xlsx or .csv file")
*/
protected $file;
/**
* @return mixed
*/
public function getFile()
{
return $this->file;
}
/**
* @param mixed $file
*/
public function setFile($file): void
{
$this->file = $file;
}
}
它适用于 macos(不关心浏览器)上的所有情况,但不适用于 Windows。
{
"status": false,"message": "error","data": {
"line": 109,"file": "\/var\/www\/vendor\/PHPoffice\/PHPspreadsheet\/src\/PHPSpreadsheet\/Shared\/OLERead.PHP","msg": "The filename \/tmp\/PHPEkOjfh is not recognised as an OLE file","trace": "#0 \/var\/www\/vendor\/PHPoffice\/PHPspreadsheet\/src\/PHPSpreadsheet\/Reader\/Xls.PHP(1367): PHPOffice\\PHPSpreadsheet\\Shared\\OLERead-\u003Eread(\u0027\/tmp\/PHPEkOjfh\u0027)\n#1 \/var\/www\/vendor\/PHPoffice\/PHPspreadsheet\/src\/PHPSpreadsheet\/Reader\/Xls.PHP(631): PHPOffice\\PHPSpreadsheet\\Reader\\Xls-\u003EloadOLE(\u0027\/tmp\/PHPEkOjfh\u0027)\n#2 \/var\/www\/src\/ApiBundle\/Controller\/HashGeneratorController.PHP(109): PHPOffice\\PHPSpreadsheet\\Reader\\Xls-\u003Eload(\u0027\/tmp\/PHPEkOjfh\u0027)\n#3 \/var\/www\/src\/ApiBundle\/Controller\/HashGeneratorController.PHP(51): ApiBundle\\Controller\\HashGeneratorController-\u003EreadFile(Object(Symfony\\Component\\HttpFoundation\\File\\UploadedFile))\n#4 \/var\/www\/vendor\/symfony\/http-kernel\/HttpKernel.PHP(158): ApiBundle\\Controller\\HashGeneratorController-\u003EprocessHash(Object(Symfony\\Component\\HttpFoundation\\Request),Object(App\\Requests\\HashGenerator\\HashGeneratorRequest))\n#5 \/var\/www\/vendor\/symfony\/http-kernel\/HttpKernel.PHP(80): Symfony\\Component\\HttpKernel\\HttpKernel-\u003EhandleRaw(Object(Symfony\\Component\\HttpFoundation\\Request),1)\n#6 \/var\/www\/vendor\/symfony\/http-kernel\/Kernel.PHP(201): Symfony\\Component\\HttpKernel\\HttpKernel-\u003Ehandle(Object(Symfony\\Component\\HttpFoundation\\Request),1,true)\n#7 \/var\/www\/public\/index.PHP(25): Symfony\\Component\\HttpKernel\\Kernel-\u003Ehandle(Object(Symfony\\Component\\HttpFoundation\\Request))\n#8 {main}"
}
}
我尝试打开标头请求以查看表单数据:
- 在 MacOS 上:
------WebKitFormBoundaryFZvmvFXVTvuUNp1h
Content-disposition: form-data; name="file"; filename="test-hash-mac.csv"
Content-Type: text/csv
------WebKitFormBoundaryFZvmvFXVTvuUNp1h--
- 在 Windows 上:
------WebKitFormBoundaryNKfDVARlcJappYQJ
Content-disposition: form-data; name="file"; filename="test-hash-mac.csv"
Content-Type: application/vnd.ms-excel
------WebKitFormBoundaryNKfDVARlcJappYQJ--
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)