php异步处理下载文件,异步处理Excel文件导入【流程图+PHP示例】

面向管理后台的系统中,经常会有文件导入的需求。常规的做法就是同步等待,但在业务关系复杂(多表数据校验)、数据量较大的情况下,管理人员只能等结果,也可能会等到超时。

使用异步的话,将导入数据的功能与后端接口解耦,避免接口超时导致的任务中止,也无需前端只为了拿个结果一直保持连接等待。

前端在上传文件后,后端接口将导入任务推送(MQ、管道...)出去,然后直接返回前端。导入服务接到任务执行导入,并根据需求将实时导入状态维护到缓存中。前端查询/轮询后端从缓存取出当前导入状态。

流程图如下:

674e18dbc684

异步导入.png

简单的PHP + Swoole后端代码示例(实际就两个接口方法upFile、importStatus,和Task的导入处理):

/**

* Created by PhpStorm.

* User: wen

* Date: 2018/12/8

* Time: 11:09 PM

*/

require 'vendor/autoload.php';

use Swoole\Http\Server;

const BASE_DIR = __DIR__;

// 路由定义

$router = [

'GET' => [

'/importStatus' => 'importStatus' // 查询导入状态

],

'POST' => [

'/upFile' => 'upFile' // 上传导入文件

]

];

// ----SWOOLE-HTTP服务设置部分

$http = new Server("127.0.0.1", 9501);

$http->set([

'worker_num' => 2,

'task_worker_num' => 4,

]);

$http->on('request', function ($request, $response) use ($router, $http) {

$funName = $router[$request->server['request_method']][$request->server['request_uri']] ?? 'NotFound';

if (!function_exists($funName)){

return backJson($response, null, 404, 'ROUTER NOT FOUND');

}

try{

$funName($request, $response, $http);

}catch (Exception $e){

return backJson($response, null, 500, $e->getMessage());

}

});

// 实际导入操作

$http->on('Task', function (swoole_server $serv, $task_id, $from_id, $data) {

$redis = getNewRedis();

$status = [

'step' => 1, // 文件准备处理

'progressRate' => '',

'info' => [],

];

$redis->set($data, json_encode($status, JSON_UNESCAPED_UNICODE));

// 读取文件 使用了PhpOffice\PhpSpreadsheet解析EXCEL

$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load(BASE_DIR . '/' . $data);

$sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);

$count = count($sheetData);

$status['step'] = 2; // 文件解析完成

$status['progressRate'] = "解析到文件数据{$count}条";

$redis->set($data, json_encode($status, JSON_UNESCAPED_UNICODE));

$names = [];

var_dump($sheetData);

foreach ($sheetData as $k => $item){

if (1==$k) continue; // 第一行为表头

if (empty($item['A'])) {

unset($sheetData[$k]);

$status['info'][] = "第{$k}行姓名为空";

continue;

}

$names[] = $item['A'];

}

$redis->set($data, json_encode($status, JSON_UNESCAPED_UNICODE));

// TODO: 验证数据库name是否已存在 插入等业务处理...(此处代码省略)

// TODO: 将进度维护到redis

});

$http->on('Finish', function () {});

// ----基础函数部分

function getNewRedis(){

($redis = new \Redis())->connect('127.0.0.1');

return $redis;

}

function backJson($response, $content, $statusCode=200, $msg=''){

$response->header('Content-Type', 'application/json');

$jsonData = [

'statusCode' => $statusCode,

'content' => $content,

'msg' => $msg,

];

$response->end(json_encode($jsonData, JSON_UNESCAPED_UNICODE));

return true;

}

function NotFound($request, $response){

return backJson($response, null, 404, 'ROUTER NOT FOUND');

}

// ----接口方法

// 上传文件

function upFile($request, $response, $server){

$file = $request->files['file'] ?? null;

if (empty($file)) { throw new Exception('未收到上传文件'); }

$importSN = md5($file['tmp_name'] . time()) . '.' . pathinfo($file['name'])['extension'];

$bol = move_uploaded_file($file['tmp_name'], BASE_DIR . '/' . $importSN);

if (false === $bol) { throw new Exception('文件处理异常'); }

$status = [

'step' => '0',

'progressRate' => '',

'info' => [],

];

getNewRedis()->set($importSN, json_encode($status, JSON_UNESCAPED_UNICODE));

$server->task($importSN);

return backJson($response, ['importSN'=>$importSN]);

}

// 查询导入状态

function importStatus($request, $response){

$importSN = $request->get['importSN'] ?? null;

if (!$importSN){ throw new Exception('导入任务编号不正确'); }

$redis = getNewRedis();

$content = $redis->get($importSN);

if (!$content){ throw new Exception('未查询到任务'); }

return backJson($response, json_decode($content));

}

$http->start();

PostMan访问示例:

674e18dbc684

屏幕快照 2018-12-09 上午4.06.17.png

674e18dbc684

屏幕快照 2018-12-09 上午4.04.16.png

674e18dbc684

屏幕快照 2018-12-09 上午4.04.50.png

这里主要是任务投递的渠道,如Channel、MQ服务、Unix Socket等。

Channel:最简单好用,同服务进程内通信,进程挂了就都gg

MQ服务:独立服务,简单通用,可以多服务器,可靠性高

Unix Socket:单服务器内进程间通信,偏底层

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260243.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 简易 blog,PHP实现简易blog的制作

最近,有时间看了点PHP的代码。参考PHP100教程做了简单的blog,这里面简单的记录一下。首先是集成环境,这里选用的WAMP:http://www.wampserver.com/en/首先通过,phpMyAdmin创建一张blog表。纯界面操作,过程比…

离散数学反对称关系_《离散数学》学习记录 - 集合论

来源&#xff1a;北京大学《离散数学》公开课地址&#xff1a;https://www.bilibili.com/video/av18896337/?p122.1 有序对和卡氏积有序对<a,b>&#xff1a;有顺序&#xff0c;类似于数组&#xff0c;可以用集合定义。性质&#xff1a;有序对内元素对应相等卡氏积AB&…

php创建表并插入数据,php数据库操作-创建库和表以及插入数据

以上我们正确连接到了mysql数据库&#xff0c;本文将进一步创建数据库&#xff0c;表&#xff0c;在表中填充数据。大家知道连接上数据库才能进行操作&#xff0c;同样的代码搬过来/** 数据库操作*(创建数据库&#xff0c;表&#xff0c;插入数据&#xff0c;插入多条数据)** T…

mysql触发器 当记录的指定字段发生变化时,更新表中的另外一个字段,或者更新另外一张关联表中关联记录的字段...

2019独角兽企业重金招聘Python工程师标准>>> 注意&#xff1a;语句中出现的old&#xff0c;new&#xff0c;now&#xff08;&#xff09;&#xff0c;都为数据库自带的关键字&#xff0c;此处不做解释。 两种情况&#xff1a; 第一种&#xff1a;一张表中&#xff0…

通用无线设备对码软件_珞光全新发布国产通用软件无线电平台 :USRP-LW N310!珞光品牌已实现国产替代...

USRP-LW N310是一种网络的软件定义无线电&#xff08;SDR&#xff09;&#xff0c;它提供了部署大规模的可靠的和容错性的分布式无线系统。USRP-LW N310通过引入远程执行任务的能力简化了对SDR系统的控制和管理&#xff0c;如更新软件&#xff0c;重新启动&#xff0c;工厂复位…

手把手玩转win8开发系列课程(2)

对win8开发&#xff0c;上一节我们对win8进行了简单的介绍&#xff0c;这一节我们来瞧一瞧他的开发环境搭建。 前奏。 这里所讲的win8开发&#xff0c;主要是指Windows8 app store 上开发&#xff0c;及metro ui或叫morden ui 程序的开发。传统桌面应用程序&#xff0c;网站应…

cordova-plugin-app-version插件使用

此插件用来获取开发软件的版本号&#xff01;首先安装此插件&#xff1a; 命令行中输入 cordova plugin add cordova-plugin-app-version然后刷新项目&#xff0c;就会在在项目plugins文件夹下看到cordova-plugin-app-version,如下图所示接下来就是使用此插件的语句获取版本号c…

不同串口通信速率超时时间_串口知识详解 串口功能及电路介绍

一、串口的概念串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口(通常指COM接口)&#xff0c;是采用串行通信方式的扩展接口。串行接口(SerialInterface)是指数据一位一位地顺序传送&#xff0c;其特点是通信线路简单&#xff0c;只要一对传输线就可以实现双向通信…

代码生成那点事

在微软技术中浸淫6年多了&#xff0c;我就常想啊&#xff0c;有没有一个工具&#xff0c;能让开发简单一点&#xff0c;哪怕就简单一点点&#xff1f;&#xff01; 这还是去年的事情&#xff0c;手里的项目都成功上线了&#xff0c;我和james聊天&#xff0c;我说咱们的这几个项…

HDU 1003 Max Sum

同上题一样&#xff0c;求连续子序列的最大和 而且比上题还要简单一些&#xff0c;用不到long long了 直接水过 1 //#define LOCAL2 #include <iostream>3 #include <cstdio>4 #include <cstring>5 using namespace std;6 7 const int maxn 100000 10;8 in…

百度关键词抓取工具_VBA利用XMLHTTP抓取百度查询关键词结果的个数

大家好,我们今日讲解"利用XMLHTTP抓取百度查询关键词结果的个数"&#xff0c;这节内容是"VBA信息获取与处理"教程中第六个专题"VBA中利用XMLHTTP完成网抓数据"的第二节。第二节 利用XMLHTTP抓取百度查询关键词结果的个数在上一讲中我们讲解了一些…

多系统通讯-DotNetMQ

很久都没有写博客了&#xff0c;从15年4月份一直忙到现在&#xff0c;我才有时间去做梳理和总结&#xff0c;因为我提离职了&#xff0c;感觉整个世界突然变得不一样&#xff0c;随着而来的就是心情的放松&#xff0c;写一篇文章也是对过去一年多工作的梳理&#xff0c;加深印象…

九大现代病!中枪了吗?

现代人在享受现代化的生活和工作方式带来的便捷之时&#xff0c;也为此付出了不小的代价&#xff0c;下面列出的九大现代病就是典型的例子&#xff0c;看看你有没有中枪。 办公臀 常坐办公室&#xff0c;如果你发现屁股越坐越大&#xff0c;大腿越坐越粗&#xff0c;你可能有了…

驱动提取软件_深入分析施耐德工控软件代码执行漏洞

更多全球网络安全资讯尽在邑安全简介在本文中&#xff0c;我们将为读者详细介绍Claroty Research团队的Amir Preminger和Sharon Brizinov是如何组合利用两个漏洞&#xff0c;来触发施耐德工控软件EcoStruxure Operator Terminal Expert的代码执行漏洞&#xff0c;从而在首届举办…

atitit.表单验证 的dsl 本质跟 easyui ligerui比较

atitit.表单验证的dsl 本质跟 easyui ligerui比较 1. DSL 声明验证 1 2. 自定义规则 1 3. 正则表达式验证,可以扩展实现 2 4. 犯错误消息提示,generic canBeEmpty is good 3 5. Prevent the form to submit when invalid 3 6. 为空则不验证&#xff0c;不为空则验证&#xff0…

企业级应用框架(五)IOC容器在框架中的应用

前言 在上一篇我大致的介绍了这个系列所涉及到的知识点&#xff0c;在本篇我打算把IOC这一块单独提取出来讲&#xff0c;因为IOC容器在解除框架层与层之间的耦合有着不可磨灭的作用。当然在本系列前面的三篇中我也提供了一种基于反射的解耦方式&#xff0c;但是始终不是很优雅&…

后端开发需要学什么_都2020年了,还在纠结学什么语言?| 后端篇

几个礼拜前&#xff0c;一个学弟问我&#xff1a;“Ray&#xff0c;我打算之后要找工作了&#xff0c;不过现在自己没有特别深入的语言&#xff0c;最近想找一门好好学一下&#xff0c;你觉得学什么语言好呀&#xff1f;”我表示&#xff1a;“这个要看你求职方向、个人喜好、市…

10个非常有用的CSS hack和技术

转自&#xff1a;http://www.qianduan.net/10-useful-css-hacks-and-technique.html 1 – 跨浏览器的inline-block <style>li {width: 200px;min-height: 250px;border: 1px solid #000;display: -moz-inline-stack;display: inline-block;margin: 5px;zoom: 1;*display:…

Java的递归算法

递归算法设计的基本思想是&#xff1a;对于一个复杂的问题&#xff0c;把原问题分解为若干个相对简单类同的子问题&#xff0c;继续下去直到子问题简单到可以直接求解&#xff0c;也就是说到了递推的出口&#xff0c;这样原问题就有递推得解。 关键要抓住的是&#xff1a; &…

发现Java程序中的Bug

昨天在CSDN上阅读 "Java中十个常见的违规编码"这篇文章时&#xff0c;无意中找到了3个 "发现Java程序中的Bug"工具。 文章地址&#xff1a;http://www.csdn.net/article/2012-09-11/2809829-common-code-violations-in-java其中&#xff0c; FindBugs™ - …