我正在使用Laravel(v5.7)应用程序,该应用程序将上传的CSV(带有联系人)转换为数组,然后在调度作业类时将其作为参数传递。
这里是CSV文件(支持的格式)的示例:
123456,Richard,Smith
654321,John,Doe
上传的(CSV)文件是这样处理的:
$file_path = $request->file_name->store('contacts');
$file = storage_path('app/' . $file_path);
$contactsIterator = $this->getContacts($file);
$contacts = iterator_to_array($contactsIterator); // Array of contacts from uploaded CSV file
protected function getContacts($file)
{
$f = fopen($file, 'r');
while ($line = fgets($f))
{
$row = explode(",", $line);
yield [
'phone' => !empty($row[0]) ? trim($row[0]) : '',
'firstname' => !empty($row[1]) ? trim($row[1]) : '',
'lastname' => !empty($row[2]) ? trim($row[2]) : '',
];
}
}
最后,$contacts
数组传递到已分派的作业:
ImportContacts::dispatch($contacts);
此工作类别如下:
public function __construct($contacts)
{
Log::info('ImportContacts@__construct START');
$this->contacts = $contacts;
Log::info('ImportContacts@__construct END');
}
public function handle()
{
Log::info('ImportContacts@handle');
}
...并且一切正常,直到我尝试使用此CSV为止(没有错误):
123456,Richardÿ,Smith
654321,John,Doe
请注意ÿ
。因此,当我尝试使用此CSV时-出现此错误异常:
/code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php | 91 | Unable to JSON encode payload. Error code: 5
...而且我的日志文件如下所示:
error local 2019-11-11 17:17:18 /code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php | 91 | Unable to JSON encode payload. Error code: 5
info local 2019-11-11 17:17:18 ImportContacts@__construct END
info local 2019-11-11 17:17:18 ImportContacts@__construct START
您可以看到-从未执行过handle
方法。如果删除ÿ
-没有错误,则执行handle
。
utf8_encode
: protected function getContacts($file, $listId)
{
$f = fopen($file, 'r');
while ($line = fgets($f))
{
$row = explode(",", $line);
yield [
'phone' => !empty($row[0]) ? utf8_encode($row[0]) : '',
'firstname' => !empty($row[1]) ? utf8_encode($row[1]) : '',
'lastname' => !empty($row[2]) ? utf8_encode($row[2]) : '',
];
}
}
...并且它works(没有错误,无论是否存在ÿ
),但是随后希腊字母和西里尔字母变成了问号。例如,此:Εθνικής
将变为???????
。
我也尝试过使用mb_convert_encoding($row[1], 'utf-8')
-并不会将希腊字母或西里尔字母变成问号,但是此ÿ
字符将变为?
。
@handle
方法中有效,但是后来我无法将该数组中的数据存储到DB(MongoDB)中。请参阅下面的更新。这是我从dd($contacts);
中得到的:
因此,它在ÿ
处具有“ b”。并且,在进行一些“搜索”之后,我发现此“ b”表示“二进制字符串”,即非Unicode字符串,其功能在字节级别(What does the b in front of string literals do?)上运行。
我了解的是:调度Job类时,Laravel尝试对其进行“ JSON编码”(传递的参数/数据),但是由于存在二进制数据(非Unicode字符串)而失败。无论如何,我找不到解决方案(能够使用ÿ
处理此类CSV文件)。
我正在使用:
当我将上传的CSV文件的“处理”(转换为数组)移到Job类的@handle
方法中时-我没有收到此错误(Unable to JSON encode payload. Error code: 5
),但是当我尝试存储有问题的二进制数据时与ÿ
(b"Richardÿ"
)进入MongoDB-失败。奇怪的是,我在日志文件中没有得到任何错误例外message,所以我将所有内容都放在try-catch中,如下所示:
try {
// Insert data into MongoDB
} catch (Exception $e) {
Log::info($e->getFile());
Log::info($e->getLine());
Log::info($e->getMessage());
}
...这是结果:
[无论如何,我相信它由于b"Richardÿ"
而失败,并且我猜想解决方案是在编码字符串中,但是正如我已经提到的那样-我无法找到有效的解决方案:
utf8_encode
起作用(没有错误,无论是否有ÿ
),但随后希腊字母和西里尔字母变成了问号。例如,此:Εθνικής
将变为???????
mb_convert_encoding($row[1], 'utf-8')
-它不会将希腊字母或西里尔字母变成问号,但此ÿ
字符将变为?
。iconv('windows-1252', 'UTF-8', $row[1])
-可以工作(没有错误,无论是否有ÿ
),但是当有希腊字母或西里尔字母时-会失败(我收到此错误异常:iconv(): Detected an illegal character in input string
)您遇到的错误是UTF8编码问题,在将行值发送到作业之前,请尝试通过utf8_encode()传递行值。