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.pswp.cn/news/260243.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260243.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260243.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

tcp client.cs

public class stateobject { public socket worksocket null; public const int Buffer_Size2048; public byte[] buffer new byte[Buffer_size]; public stringbuilder sb new stringbuilder(); } 轉載于:https://www.cnblogs.com/neumik/archive/2012/11/15/2771024.ht…

[python] 之 常用內建函數

本博客僅列舉了一些常用的內建函數,歡迎大家補充! 1. dir([obj]) 顯示對象的屬性,若果沒有提供參數,則顯示全局變量的名字 2. help([obj]) 以一種整齊美觀的方式,顯示對象的文檔字符串;如果沒有提供任何參數…

python查詢模塊所有類_python 小技巧(import模塊、查詢類繼承關系、安裝包)

作者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!在這里列舉一些我使用Python時積累的小技巧。這些技巧是我在使用Python過程中經常使用的。之前很零碎的記在筆記本中,現在整理出來&am…

4.2 access函數實例

int access(const char *filenpath, int mode); 功 能: 確定文件或文件夾的訪問權限。 mode,要判斷的模式在頭文件unistd.h中的預定義如下:#define R_OK 4 /* Test for read permission. */#define W_OK 2 /* Test for write permission. */#define X_OK…

php 簡易 blog,PHP實現簡易blog的制作

最近,有時間看了點PHP的代碼。參考PHP100教程做了簡單的blog,這里面簡單的記錄一下。首先是集成環境,這里選用的WAMP:http://www.wampserver.com/en/首先通過,phpMyAdmin創建一張blog表。純界面操作,過程比…

jquery 事件對象屬性小結

jquery 事件對象屬性小結 使用事件自然少不了事件對象. 因為不同瀏覽器之間事件對象的獲取, 以及事件對象的屬性都有差異, 導致我們很難跨瀏覽器使用事件對象. jQuery中統一了事件對象, 當綁定事件處理函數時, 會將jQuery格式化后的事件對象作為唯一參數傳入: $("#testDiv…

ABP文檔 - Mvc 視圖

文檔目錄 本節內容: 簡介AbpWebViewPage 基類簡介 ABP通過nuget包Abp.Web.Mvc集成到Mvc視圖里,你可以像往常那樣創建常規的視圖。 AbpWebViewPage 基類 ABP也提供了AbpWebViewPage,它定義了一些有用的屬性和方法,如果你使用啟動模…

ThinkPad L440 FN鍵設置

剛入手了ThinkPad L440,用起來相當不錯,嘿嘿! L440系統默認(F1-F12)鍵盤為系統默認功能鍵,主要控制音量、亮度、連接投影儀等。 因為編寫程序需要調試,經常用到F10,F11等鍵&#xff…

離散數學反對稱關系_《離散數學》學習記錄 - 集合論

來源&#xff1a;北京大學《離散數學》公開課地址&#xff1a;https://www.bilibili.com/video/av18896337/?p122.1 有序對和卡氏積有序對<a,b>&#xff1a;有順序&#xff0c;類似于數組&#xff0c;可以用集合定義。性質&#xff1a;有序對內元素對應相等卡氏積AB&…

收集的博客列表

前端&#xff1a; ———————————————————— 宅居 - 裸: http://otakustay.com/ 轉載于:https://www.cnblogs.com/ccdc/archive/2012/11/21/2780879.html

php創建表并插入數據,php數據庫操作-創建庫和表以及插入數據

以上我們正確連接到了mysql數據庫&#xff0c;本文將進一步創建數據庫&#xff0c;表&#xff0c;在表中填充數據。大家知道連接上數據庫才能進行操作&#xff0c;同樣的代碼搬過來/** 數據庫操作*(創建數據庫&#xff0c;表&#xff0c;插入數據&#xff0c;插入多條數據)** T…

C#配置及使用log4net

首先從官方網站http://logging.apache.org/log4net/下載最近版本的log4net組件。在程序中添加對log4net.dll的引用&#xff0c;就可以在程序中使用了。 下一步&#xff0c;編寫配置文件&#xff0c;內容如下 <?xml version"1.0" encoding"utf-8" ?>…

ORACLE EBS常用表及查詢語句(最終整理版)

建議去看參考二 參考一&#xff1a; call fnd_global.APPS_INITIALIZE(1318,50583,401) select fnd_profile.VALUE(ORG_ID) FROM DUAL select * from hr_operating_units hou where hou.organization_id204 --fn…

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;網站應…

python通過什么來區分不同語句塊_Python語言通過

【填空題】小塊【填空題】離開;出發(n.)【填空題】好人啊中的 “ 啊 ” 讀( )【填空題】“ 潔癖 ” 的正確讀音是( )【單選題】The article suggests that when a person ________ under unusual stress he should be especially careful to have a well-balanced diet. (CET20…

【Android面試】Android面試題集錦 (陸續更新)

【Android面試】Android面試題集錦 (陸續更新) 分類&#xff1a; 【雜七雜八】2011-05-11 17:58 2064人閱讀 評論(0) 收藏 舉報一些常見的Android面試基礎題做下總結&#xff0c;看看你能做出多少道? 1. Intent的幾種有關Activity啟動的方式有哪些&#xff0c;你了解每個含義嗎…

cordova-plugin-app-version插件使用

此插件用來獲取開發軟件的版本號&#xff01;首先安裝此插件&#xff1a; 命令行中輸入 cordova plugin add cordova-plugin-app-version然后刷新項目&#xff0c;就會在在項目plugins文件夾下看到cordova-plugin-app-version,如下圖所示接下來就是使用此插件的語句獲取版本號c…

14.cookie與自動登陸

場景 webdriver可以讀取并添加cookie。有時候我們需要驗證瀏覽器中是否存在某個cookie&#xff0c;因為基于真實的cookie的測試是無法通過白盒和集成測試完成的。 另外更加常見的一個場景是自動登陸。有很多系統的登陸信息都是保存在cookie里的&#xff0c;因此只要往cookie中添…