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

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

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

流程图如下:

异步导入.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访问示例:

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

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

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

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

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

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

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

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

  1. Python合并同文件夹下面Excel文件并且求和汇总

    Python合并同文件夹下面Excel文件并且求和汇总 将程序放到Excel的文件夹下执行即可 import openpyxl,os,xlrd,time import pandas as pd imp ...

  2. R语言write.xlsx函数将数据写入Excel文件:写入Excel文件并自定义表单的名称、将数据写入Excel文件新的表单(sheet)中、将文件保存为xls文件格式(而不是xlsx)

    R语言write.xlsx函数将数据写入Excel文件:写入Excel文件并自定义表单的名称.将数据写入Excel文件新的表单(sheet)中.将文件保存为xls文件格式(而不是xlsx) 目录

  3. python怎么读excel文件-python读写excel文件

    项目中需要生成excel表格,在网上查了一些资料后,整理记录下. 1. 读excel表格 1 ''' 2 读取XLS,XLSX文件3 ''' 4 defreadExcelFile(filename): ...

  4. JS 判断上传文件是否为EXCEL 文件

    <SCRIPT language="JavaScript"> function checkform(o){var f_content = form1.file.valu ...

  5. 小白用python处理excel文件-Python3操作Excel文件(读写)的简单实例

    安装 读Excel文件通过模块xlrd 写Excel文件同过模块xlwt(可惜的是只支持Python2.3到Python2.7版本) xlwt-future模块,支持Python3.X,用法据说与xl ...

  6. 怎么把excel文件转成dta_如何将excel表格数据转化为dta格式-怎么把dat文件转换成Excel文件,里面的数据格式要......

    dat文件怎么转换成excel 1.首先点击excel表格左上角的"文件"选项. 2.在打开的页面中点击"另存为"选项并点击其中的"浏览"按 ...

  7. matlab依次读取每个数,『matlab如何依次读取文件夹中EXCEL文件,并对每一个EXCEL特定列全部数值进行处理?』matlab调入excel文件的某一列...

    matlab导入excel表格,第一行为x,第一列为y的数据,其余为z 行的NI(r=1--0.25)比烦. filename='a.xls';%,可据你的需要更改 y=xlsread(filenam ...

  8. node-xlsx 生成并下载有超链接的excel文件

    需求:将微信小程序云数据库中的数据导出为excel文件,文件按团队分为不同的sheet页,首页汇总每个sheet页的数据总数,并可点击跳转至对应的sheet页.下载时可选择今年某月份进行下载对应的数据 ...

  9. python读取python源代码文件_python 读写excel文件操作示例【附源码下载】

    本文实例讲述了python 读写excel文件操作.分享给大家供大家参考,具体如下: 对excel文件的操作,python有第三方的工具包支持,xlutils,在这个工具包中包含了xlrd,xlwt等 ...

  10. 用ajax下载字节流形式的excel文件

    原因:ajax请求只是个"字符型"的请求,即请求的内容是以文本类型存放的.文件的下载是以二进制形式进行的,ajax没法解析后台返回的文件流,所以无法处理二进制流response输出 ...

最新文章

  1. 网络公开课资源 ——关注CS/AI/Math
  2. 我的世界java版导入地图_网易我的世界备份与导入地图
  3. java 异或_脚本语言系列之Java | Java中的运算符
  4. python如何提交作业_玛雅截稿作业提交python命令
  5. 支付宝放出数字化经营新神器,可提升商家60%消费频次
  6. 如何更有价值采集数据、高效分析数据?
  7. iPhone 14系列影像规格曝光:长焦镜头或再度缺席
  8. Java方法重载时参数类型有重合,它会选择执行哪一个?
  9. 【hihocoder 1032】最长回文子串
  10. 华为网络工程师认证有哪些?值不值得考?
  11. linux系统编译Q,Linux下安装qBittorrent,开启24小时挂机BT下载
  12. ADSL拨号工作原理
  13. python123第四周_百度杯十月第四周WriteUp
  14. Apple Watch更懂女人心
  15. 海尔微型计算机云悦t3G276ia,没了海尔云悦miniA 迷你主机界尽失半壁江山
  16. 基于粒子群优化算法的最小二乘支持向量机预测模型构建(MATLAB实现)
  17. 计算机word表格基础,Word表格的作-计算机基础.doc
  18. 小米/红米手机如何通过USB数据线把手机网络共享给电脑
  19. 什么样的企业/单位需要圣天诺LDK?
  20. TP-Link家用路由器上网与防蹭网

热门文章

  1. 蓝桥杯——机器人行走
  2. (php)实现万年历
  3. es6 var、let、const命令
  4. C/C++ 中变量的声明、定义、初始化的区别
  5. 常用JQuery插件整理
  6. docker --- 将已有的项目发布到云端
  7. tomcat启动报错The JRE could not be found.Edit the server and change the JRE location
  8. 前端每日实战:56# 视频演示如何用纯 CSS 描述程序员的生活
  9. 大数据和人工智能的关系是什么?
  10. 52.4. APC Cache (php-apc - APC (Alternative PHP Cache) module for PHP 5)