使用Laravel 4.2导入Maatwebsite / Excel失败
I'm writing a web-app to parse Excel files, each contains a lot of data (~47 columns and thousands of rows). The framework is Laravel 4.2 and the package used is laravel-excel (maatwebsite/excel).
When I wrote all the code, I had a sample file from the customer, it contained 620 rows and everything worked fine. Now, some files work and most of them do not. The errors are strange. Ok, step by step:
Logic
A user selects a file via <input type="file">
, then this file is sent to the server via $.ajax
, the server creates a Job
instance with properties of this file and returns this instance to the client. Client receives this Job
instance and sees if progress
for this Job
(i.e. number of rows parsed) is lower than total
(i.e. total number of rows). If it is so, the client sends a request to the server to execute this Job
(i.e. to parse a certain amount of rows more, e.g. 200). So there is always a dialogue between the client and server, something like this:
-
Client: Dear Server, hereby I upload this file
orders_123.xlsx
. -
Server: Dear Client, thank you, I stored your file and created a
Job
withid = 27
. Your file hastotal = 623
rows, and the currentprogress = 0
. -
Client: Dear Server, thank you, please, execute this
Job
withid = 27
, taking200
rows. Reply ASAP. -
Server: Dear Client, I did what you asked, your
Job
withid = 27
now hasprogress = 200
. -
Client: Ok, Server, please, execute this
Job
again and again take200
rows. - And so it continues, until the Job is finished.
You may ask why I did it so strangely instead of just asking the server to import ALL of rows, but here again, I found that some dark magic is involved here, and this way is the only way it works most of the time (the server fails otherwise).
JavaScript
function uploadFile(file) {
var data = new FormData();
data.append("file", file);
showProgressBar(file.name);
$.ajax({
type: "POST",
url: "/import/orders",
data: data,
cache: false,
processData: false,
contentType: false,
success: function(response) {
if (response.status == "error") {
hideProgressBar(file.name + ": Error! " + response.data, response.status);
} else if (response.status == "success") {
executeJob(response.job, 100);
}
},
xhr: function() {
var xhr = $.ajaxSettings.xhr();
if (typeof xhr.upload === "object") {
xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) {
var val = Math.floor(100 * e.total / e.loaded)
updateProgressBar(val);
}
}, false);
}
return xhr;
}
});
}
function executeJob(job, take) {
$.ajax({
type: "POST",
url: "/jobs/execute",
data: {
job: job,
take: take
},
success: function(response) {
if (response.status == "error") {
hideProgressBar(job.original_name + ": Error! " + response.data, response.status);
} else if (response.status == "success") {
updateProgressBar(Math.floor(100 * response.job.progress / response.job.total));
if (val >= 100) {
hideProgressBar(job.original_name + ": Success!", response.status)
deleteJob(job);
} else {
executeJob(job, take);
}
}
}
}, "json");
}
Routes
Route::post('/import/orders', array('before' => 'csrf', 'uses' => 'OrdersFPController@handleOrdersImport'));
Route::post('/jobs/execute', array('before' => 'csrf', 'uses' => 'JobsController@handleExecute'));
Route::post('/jobs/delete', array('before' => 'csrf', 'uses' => 'JobsController@handleDelete'));
OrdersFPController@handleOrdersImport
class OrdersFPController extends BaseController {
public function handleOrdersImport()
{
$file = Input::file('file');
$fields = ['order', 'location', ...];
if (!$file->isValid()) {
return Response::json(array('status' => 'error', 'data' => 'File is invalid.'));
}
$filename = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$extension_guessed = $file->guessExtension();
if ($extension != $extension_guessed) {
return Response::json(array('status' => 'error', 'data' => 'Wrong extension of the file: ".' . $extension . '", should be ".' . $extension_guessed . '".'));
}
$filename_new = str_random(20) . '.' . $extension;
$path = public_path() . '/assets/import/orders';
$file->move($path, $filename_new);
$sheet = Excel::load($path . '/' . $filename_new, function($reader) {})->get();
if (is_null($sheet)) {
File::delete($path . '/' . $filename_new);
return Response::json(array('status' => 'error', 'data' => 'Could not load any sheets in the file.'));
}
$job_total = $sheet->count();
if ($job_total < 1) {
File::delete($path . '/' . $filename_new);
return Response::json(array('status' => 'error', 'data' => 'No data could be read in the file.'));
}
$sample = $sheet[0];
foreach($fields as $f) {
if (!isset($sample->$f)) {
File::delete($path . '/' . $filename_new);
return Response::json(array('status' => 'error', 'data' => 'Fields are missing for the selected type.'));
}
}
$job = new Job;
$job->type = 'orders';
$job->link = $path . '/' . $filename_new;
$job->original_name = $filename;
$job->total = $job_total;
$job->user()->associate(Auth::user());
$job->save();
return Response::json(array('status' => 'success', 'job' => $job, 'data' => 'File uploaded.'));
}
}
The problem is that sometimes when the script reaches $sheet = Excel::load($path . '/' . $filename_new, function($reader) {})->get();
, the server returns Error 500 (Internal server error)
. Sometimes it even kills my server (no kidding), stopping the php artisan serve
command in the terminal. Some screenshots:
Safari
http://i.stack.imgur.com/3gkpr.png
http://i.stack.imgur.com/m8V4s.png
Firefox
http://i.stack.imgur.com/QVceP.png
http://i.stack.imgur.com/IcOQF.png
http://i.stack.imgur.com/xvFoN.png
http://i.stack.imgur.com/flx3K.png
Well, this is the problem. The server returns nothing, just an error, no description.
EDIT:
As mentioned by @lukasgeiter, I checked the log file. When the code is Excel::filter('chunk')->load($path . '/' . $filename_new)->chunk(50, function($results) { /// });
, the output is as follows:
[2015-01-28 20:00:02] production.ERROR: exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Maximum execution time of 60 seconds exceeded' in /Users/antonsinyakin/Documents/projects/sites/foodpanda/vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel2007.php:834
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleShutdown()
#1 {main} [] []
If a regular $sheet = Excel::load($path . '/' . $filename_new, function($reader) {})->get();
is used, nothing is written to the log file.
- 点赞
- 写回答
- 关注问题
- 收藏
- 复制链接分享
- 邀请回答
为你推荐
- 如何分页可用收藏[Laravel 4.2]
- Laravel 4.2 Auth ::尝试失败
- laravel 4.2复杂查询的paginate
- Updated_at使用Laravel 4.2 DB Class的时间戳
- laravel excel导出所有记录失败
- 是否可以使用Laravel Excel为整列添加边框?
- Pagodabox - 在/data/vendor/laravel/framework/src/Illuminate/Redis/Database.php:62中找不到“Predis \ Client”类
- Laravel 4.2:在会话中保留多维数组数据
- Laravel将数据导出到Excel文件中需要进行修改
- 使用Laravel 5.4导出CSV / XLSX
- withX()在Laravel 4.2中不起作用
- 子文件夹中的Laravel 4.2控制器
- 漂亮的URL使用laravel 4.2
- Laravel 4.2界面混乱
- 动态查询ORM Laravel 4.2
- 在Laravel中将数据导出到Excel
- 在laravel 4.2中登录失败
- 我在laravel中使用dingo / api。但它始终是错误404
- 使用laravel将裁剪后的图像保存在public / uploads文件夹中
- Laravel 4.2:如何在Laravel中使用SUM的顺序