内容简介:平时我们上传文件使用的是HTTP方式上传,今天我来给大家分享一下使用HTML5的websocket方式上传文件,后端使用Swoole的Websocket模块接收处理客户端上传的数据并保存为文件。本文实例是一个基础实例,后面我会专门给大家讲解更复杂更实战的文件上传实例。
平时我们上传文件使用的是HTTP方式上传,今天我来给大家分享一下使用HTML5的websocket方式上传文件,后端使用Swoole的Websocket模块接收处理客户端上传的数据并保存为文件。本文实例是一个基础实例,后面我会专门给大家讲解更复杂更实战的文件上传实例。
服务端
我们继续使用Swoole实验室: 1-使用Composer构建项目构建好的项目 ,新建文件\src\App\Uploader.php:
<?php namespace Helloweba\Swoole; use swoole_websocket_server; class Uploader { protected $ws; protected $host = '0.0.0.0'; protected $port = 9505; // 进程名称 protected $taskName = 'swooleUploader'; // PID路径 protected $pidFile = '/run/swooleUploader.pid'; // 设置运行时参数 protected $options = [ 'worker_num' => 4, //worker进程数,一般设置为CPU数的1-4倍 'daemonize' => true, //启用守护进程 'log_file' => '/data/log/swoole.log', //指定swoole错误日志文件 'log_level' => 3, //日志级别 范围是0-5,0-DEBUG,1-TRACE,2-INFO,3-NOTICE,4-WARNING,5-ERROR 'dispatch_mode' => 1, //数据包分发策略,1-轮询模式 ]; public function __construct($options = []) { $this->ws = new swoole_websocket_server($this->host, $this->port); if (!empty($options)) { $this->options = array_merge($this->options, $options); } $this->ws->set($this->options); $this->ws->on("open", [$this, 'onOpen']); $this->ws->on("message", [$this, 'onMessage']); $this->ws->on("close", [$this, 'onClose']); } public function start() { // Run worker $this->ws->start(); } public function onOpen(swoole_websocket_server $ws, $request) { // 设置进程名 cli_set_process_title($this->taskName); //记录进程id,脚本实现自动重启 $pid = "{$ws->master_pid}\n{$ws->manager_pid}"; file_put_contents($this->pidFile, $pid); echo "server: handshake success with fd{$request->fd}\n"; $msg = '{"msg": "connect ok"}'; $ws->push($request->fd, $msg); } public function onMessage(swoole_websocket_server $ws, $frame) { $opcode = $frame->opcode; if ($opcode == 0x08) { echo "Close frame received: Code {$frame->code} Reason {$frame->reason}\n"; } else if ($opcode == 0x1) { echo "Text string\n"; } else if ($opcode == 0x2) { echo "Binary data\n"; // } else { echo "Message received: {$frame->data}\n"; } $filename = './files/aaa.jpg'; file_put_contents($filename, $frame->data); echo "file path : {$filename}\n"; $ws->push($frame->fd, 'upload success'); } public function onClose($ws, $fid) { echo "client {$fid} closed\n"; foreach ($ws->connections as $fd) { $ws->push($fd, $fid. '已断开!'); } } }
$frame->opcode
,WebSocket的OpCode类型,可以通过它来判断传输的数据是文本内容还是二进制数据。
新建public/uploadServer.php,用于启动服务端脚本:
<?php require dirname(__DIR__) . '/vendor/autoload.php'; use Helloweba\Swoole\Uploader; $opt = [ 'daemonize' => false ]; $ws = new Uploader($opt); $ws->start();
客户端
在本地站点建立客户端文件upload.html。只需在页面中放置一个文件选择控件和一个用于输出上传信息的div#log。
<input type="file" id="myFile"> <div id="log"></div>
当选择好本地文件后,触发onchange事件,这个时候客户端尝试与服务端建立websocket连接,然后开始读取本地文件,读取完成后将数据发送给服务端。
$('#myFile').on('change', function(event) { var ws = new WebSocket("ws://192.168.1.31:9505"); ws.onopen = function() { log('已连接上!'); } ws.onmessage = function(e) { log("收到服务器消息:" + e.data + "'\n"); if (e.data == 'connect ok') { log('开始上传文件'); } if (e.data == 'upload success') { log('上传完成'); ws.close(); } else { var file = document.getElementById("myFile").files[0]; var reader = new FileReader(); reader.readAsArrayBuffer(file); reader.onload = function(e) { ws.send(e.target.result); log('正在上传数据...'); } } } ws.onclose = function() { console.log('连接已关闭!'); log('连接已关闭!'); } }); //在消息框中打印内容 function log(text) { $("#log").append(text+"<br/>"); }
这里讲一下HTML5的FileReader 对象,FileReader允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。FileReader提供了几种读取文件的方法:
reader.readAsArrayBuffer(file|blob)
:用于启动读取指定的 Blob 或 File 内容。读取文件后,会在内存中创建一个ArrayBuffer对象(二进制缓冲区),将二进制数据存放在其中。当读取操作完成时,readyState 变成 DONE(已完成),并触发 loadend 事件,同时 result 属性中将包含一个 ArrayBuffer 对象以表示所读取文件的数据。通过此方式,可以直接在网络中传输二进制内容。此外对于大文件我们可以分段读取二进制内容上传。
reader.readAsDataURL(file|blob)
:该方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成(DONE),并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。
FileReader.readAsText(file|blob)
:可以将 Blob 或者 File 对象转根据特殊的编码格式转化为内容(字符串形式)。当转化完成后, readyState 这个参数就会转换 为 done 即完成态, event("loadend") 挂载的事件会被触发,并可以通过事件返回的形参得到中的 FileReader.result 属性得到转化后的结果。
FileReader.readAsBinaryString()
:读取文件内容为二进制字符串,已废除,不要用了。
实验
运行服务端
php uploadServer.php
运行客户端
在本地站点目录,打开upload.html。选择图片上传,即刻显示如下信息:
查看服务端输出:
这时候检查服务器上对应目录下会出现一个aaa.jpg的文件。
Swoole也提供了Websocket客户端,可以使用websocket在不同服务端传输文件。
我们会发现使用Websocket确实把文件上传成功,但是实验中并没有考虑大文件的上传,加入有一个很大的日志文件或者视频文件需要上传到服务器上,那就需要采取分片上传,并考虑断点上传的问题,在下一节文章实验中,我们将具体探讨使用Websocket上传大文件,敬请关注。
以上所述就是小编给大家介绍的《Swoole实验室:7-使用Websocket上传文件(1)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Ceph实验室:第四课:Ceph监控
- Ceph实验室:第四课:Ceph监控
- 2018Android实验室CV培训总结
- 复旦NLP实验室NLP上手教程
- Ceph实验室:第三课:Ceph服务管理
- Ceph实验室:第三课:Ceph服务管理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python for Everyone
Cay S. Horstmann、Rance D. Necaise / John Wiley & Sons / 2013-4-26 / GBP 181.99
Cay Horstmann's" Python for Everyone "provides readers with step-by-step guidance, a feature that is immensely helpful for building confidence and providing an outline for the task at hand. "Problem S......一起来看看 《Python for Everyone》 这本书的介绍吧!