谈到文件上传,就需要看workerman的文档,文档资料比较丰富,但是我觉得还是有些问题,比如PHP的Pack函数,到现在我也不知道怎么用其他语言去写,这个问题能也不能归结到PhP上,只能怪自己能力不行!,贴出Java版的Pack函数,但是我也没搞懂这个Pack
image还有就是关于网络字节序的unsigned int数据,怎么用java发,确实不知道怎么搞!最后的办法就是通过Base64来发送文件,可以完美解决跨语言发文件,因为本人最热爱,java,php,
第一步,看文档,了解Workerman的如何自定义协议,根据文档介绍,自己创建一个php 类文件文件
必须要包含三个静态方法
image image image然后分别定义一个命名空间
image该文件放在
image最后你就可以用了
贴出该文件的全部代码
/**
* Created by PhpStorm.
* User: hxm
* Date: 2018/6/1
* Time: 10:15
*/
namespace Workerman\Protocols;
/*
* {"file_name":"logo.png","file_data":"PD9waHAKLyo......"}\n
* 协议定义,这个\n,必须包含,标识一个完整的数据包结束*/
class File_protocol{
/*
* 检查包完整性 * 返回包的整体长度; * 返回0,等带下次上传 * 返回false,断开客服端的连接*
*/
public static function input($rec_buff){
// echo $rec_buff;
$recv_len = strlen($rec_buff);
if($rec_buff[$recv_len-1] !=="\n")
{
return 0;
}
return strlen($rec_buff);
}
/*
* 解包数据,该数据,并返回 * 该方法,返回后再worker实例的onMessage方法调用!*
*/
public static function decode($rec_buff){
// 解包
$package_data = json_decode(trim($rec_buff), true);
// 取出文件名
$file_name = $package_data['file_name'];
// 取出base64_encode后的文件数据
$file_data = $package_data['file_data'];
$file_data = base64_decode($file_data);
// 返回数据
return array(
'file_name' => $file_name,
'file_data' => $file_data,
);
}
/*
* 打包,当向客户端发送数据的时候会自动调用*
*/
public static function encode($rec_buff){
// 可以根据自己的需要编码发送给客户端的数据,这里只是当做文本原样返回
return $rec_buff;
}
}
最后你就可以这自己写一个文件运行了
image image接下分别采用Java和Php客服端做例子
import sun.misc.BASE64Encoder;
import java.io.*;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args)throws Exception {
Socket socket =new Socket("127.0.0.1", 8888);
//获取输出流
OutputStream out = socket.getOutputStream();
//文件编码
String s =encodeBase64File("F:\\a.rar");
//去除特殊符号
String s1 =replaceBlank(s);
//构建数据包
String pack ="{\"file_name\":\"logo.rar\",\"file_data\":\"" + s1 +"\"}\n";
out.write(pack.getBytes("UTF-8"));
out.flush();
out.close();
socket.close(); // 关闭Socket
}
/**
* @Author: 黑小马
* @Date: 2018/6/1
* @Description:出除字符串的\t\r\n
**/
public static StringreplaceBlank(String str) {
String dest ="";
if (str !=null) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(str);
dest = m.replaceAll("");
}
return dest;
}
/**
* @Author: 黑小马
* @Date: 2018/6/1
* @Description:进行文件编码
**/
public static StringencodeBase64File(String path)throws Exception {
File file =new File(path);
FileInputStream inputFile =new FileInputStream(file);
byte[] buffer =new byte[(int) file.length()];
inputFile.read(buffer);
inputFile.close();
return new BASE64Encoder().encode(buffer);
}
public static byte[]pack(String str) {
int nibbleshift =4;
int position =0;
int len = str.length() /2 + str.length() %2;
byte[] output =new byte[len];
for (char v : str.toCharArray()) {
byte n = (byte) v;
if (n >='0' && n <='9') {
n -='0';
}else if (n >='A' && n <='F') {
n -= ('A' -10);
}else if (n >='a' && n <='f') {
n -= ('a' -10);
}else {
continue;
}
output[position] |= (n << nibbleshift);
if (nibbleshift ==0) {
position++;
}
nibbleshift = (nibbleshift +4) &7;
}
return output;
}
}
php客服端
<?php
/** 上传文件客户端 **/
// 上传地址
$address = "127.0.0.1:8888";
// 检查上传文件路径参数
if(!isset($argv[1]))
{
exit("use php client.php \$file_path\n");
}
// 上传文件路径
$file_to_transfer = trim($argv[1]);
// 上传的文件本地不存在
if(!is_file($file_to_transfer))
{
exit("$file_to_transfer not exist\n");
}
// 建立socket连接
$client = stream_socket_client($address, $errno, $errmsg);
if(!$client)
{
exit("$errmsg\n");
}
stream_set_blocking($client, 1);
// 文件名
$file_name = basename($file_to_transfer);
// 文件二进制数据
$file_data = file_get_contents($file_to_transfer);
// base64编码
$file_data = base64_encode($file_data);
echo $file_data;
// 数据包
$package_data = array(
'file_name' => $file_name,
'file_data' => $file_data,
);
// 协议包 json+回车
$package = json_encode($package_data)."\n";
// 执行上传
fwrite($client, $package);
// 打印结果
echo fread($client, 8192),"\n";
以上基本 都是帖代码,但是整体思路是完全没有问题,更多的就是去看手册!
或者我应该去看看那个pack方式,baes64,编码后的整体会比源文件大一些,感觉不是很好!
网友评论