我使用的技术栈是:react-native(0.56.0)+ react-navigation + react-redux + ant-design + axios


我在做的ReactNative项目需要实现同一WIFI下跨平台互传文件功能,涉及原生模块的功能

我实现这两个功能使用的库有

  • @react-native-community/netinfo
  • NanoHTTPD

首先需要明白限制条件是在同一个局域网内(连接同一wifi),前期已经用umi开发了一组传输文件时准备在PC上展示的相关网页并打包出来。

核心技术:

通过使用NanoHTTPD在手机上建立本地服务器实现数据传输。
为了保证安全性,需要PC端输入APP生成的验证码予以验证。

整体流程:

1. 判断是否连接WIFI并获取ip地址

WifiManager是 Android 暴露给开发者使用的一个系统服务管理类, 其中包含对WiFi的响应的操作函数。

        //获取wifi服务WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);//判断wifi是否开启if (!wifiManager.isWifiEnabled()) {return null;}//判断wifi是否连接if (wifiManager.getConnectionInfo() == null) {return null;}// ip地址获取
int ipAddress = wifiManager.getConnectionInfo().getIpAddress();return (ipAddress & 0xFF) + "." +((ipAddress >> 8) & 0xFF) + "." +((ipAddress >> 16) & 0xFF) + "." +(ipAddress >> 24 & 0xFF);

2. 启动服务

主要逻辑继承NanoHTTPD,根据你的需求重写serve方法就可以了

在我写的this.openHttp(port,code,mainKey,toPage)中,code是验证码,mainkey是自定义需要传输的部分内容,toPage是判断是由手机向PC还是PC向手机传输文件。

// 随机数防止端口被占用,如果被占用catch后stopServer
int port = (int)((Math.random()*9+1)*1000);
final String host = ip + ":" + port;
this.openHttp(port,code,mainKey,toPage);
promise.resolve("http://" + host);
//
private void openHttp(int port,String code,ReadableMap mainKey, String toPage) throws IOException {httpServer = new HttpServer(getReactApplicationContext(), port,code,mainKey,toPage);httpServer.start();}

3. 自定义的serve,返回网页或者响应请求

根据不同的路径返回不同的数据

将文件转化的字符串或者数组作为响应内容返回return Response.newFixedLengthResponse(字符串)
或者return Response.newFixedLengthResponse(状态码,mime类型,字节数组)

public  Response serve(IHTTPSession session){String uri = session.getUri();// 根据html的路径返回相应的操作if (uri.equals("/postValidatePhoneCode")) {return validatecode(session);}else if (uri.equals("/upload")){return renderUpload(session);}else if (uri.equals("/getPhoneKey")){return getKey(session);}else if (uri.equals("/device")){return download(session);}else if (uri.indexOf(".json")!=-1){return downloadKey(session);} else {return renderRes(session);}}

renderRes

不带路径的url根据toPage参数返回html,保证PC访问到初始页面

private Response renderRes(IHTTPSession session) {String uri = session.getUri();String filename;if (uri.equals("/")) filename = "index.html";else filename = uri.substring(1);
// 定义mineTypeString mimeType = null; if (filename.endsWith(".html") || filename.endsWith(".htm")) {mimeType = "text/html";} else if (filename.endsWith(".js")) {mimeType = "text/javascript";} else if (filename.endsWith(".css")) {mimeType = "text/css";}else if (filename.endsWith(".ico")) {mimeType = "image/x-icon";}if (mimeType == null) {return newFixedLengthResponse(Response.Status.BAD_REQUEST, "text/plain", "未知文件类型[" + filename + "]");}InputStreamReader inputStreamReader = null;BufferedReader reader = null;try {//            filename = "Resources"+filename;inputStreamReader = new InputStreamReader(context.getAssets().open(filename));reader = new BufferedReader(inputStreamReader);StringBuilder returnMsg = new StringBuilder();String line;while ((line = reader.readLine()) != null) {returnMsg.append(line);}return newFixedLengthResponse(Response.Status.OK, mimeType, returnMsg.toString());} catch (IOException e) {Utils.closeSilent(reader);Utils.closeSilent(inputStreamReader);e.printStackTrace();return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", e.getMessage());}}

validatecode 验证验证码

            session.parseBody(files);String param=files.get("postData");JSONObject json = new JSONObject(param);String code = json.getString("code");if (code.equals(this.code+"")){Map map = new HashMap();map.put("validate",true);map.put("toPage",this.toPage);JSONObject jsonObj=new JSONObject(map);return newFixedLengthResponse(Response.Status.OK, "text/plain", jsonObj.toString());}else {Map map = new HashMap();map.put("validate",false);JSONObject jsonObj=new JSONObject(map);return newFixedLengthResponse(Response.Status.REDIRECT_SEE_OTHER, "text/plain", jsonObj.toString());}

验证码正确则跳转到相应页面,进行下载或上传

download 上传文件到PC

private Response downloadKey(IHTTPSession session) {try {File distFile = new File(this.context.getFilesDir().getAbsolutePath() + File.separatorChar + "wifi" + File.separatorChar + this.mainKey.getString("key_name") + ".json");//判断该文件的所属文件夹存不存在,不存在则创建文件夹if(!distFile.getParentFile().exists()){distFile.getParentFile().mkdirs();}//创建文件if (!distFile.exists()){//如果不存在file文件,则创建distFile.createNewFile();}//创建字符流(使用字节流比较麻烦)FileWriter fw = new FileWriter(distFile);Map map = new HashMap();map.put("address",this.mainKey.getString("pubaddress"));map.put("algo","0x03");map.put("encrypted",this.mainKey.getString("privateKeystr").substring(2,this.mainKey.getString("privateKeystr").length()));map.put("version","2.0");map.put("privateKeyEncrypted",false);JSONObject jsonObj=new JSONObject(map);fw.write(jsonObj.toString());//这里要说明一下,write方法是写入缓存区,并没有写进file文件里面,要使用flush方法才写进去fw.flush();//关闭资源fw.close();FileInputStream fis = new FileInputStream(distFile.getPath());return newFixedLengthResponse(Response.Status.OK, "application/octet-stream", fis,fis.available());} catch (FileNotFoundException e) {e.printStackTrace();return newFixedLengthResponse(Response.Status.BAD_REQUEST, "text/plain", e.getMessage());} catch (IOException e) {e.printStackTrace();return newFixedLengthResponse(Response.Status.BAD_REQUEST, "text/plain", e.getMessage());} catch (Exception e) {e.printStackTrace();return newFixedLengthResponse(Response.Status.BAD_REQUEST, "text/plain", e.getMessage());}}

upload 从PC端下载文件

private void sendUploadFileToClient(IHTTPSession session) throws IOException, ResponseException {Map<String, String> files = new HashMap<>();session.parseBody(files);Map<String, List<String>> parameters = session.getParameters();WritableArray params = Arguments.createArray();String str = "";for (String key : files.keySet()) {List<String> nameStr = parameters.get(key);if (nameStr == null) continue;File tempFile = new File(files.get(key));File distFile = new File(this.context.getFilesDir().getAbsolutePath() + File.separatorChar + "wifi" + File.separatorChar + tempFile.getName());Utils.copyFile(tempFile, distFile);//NanoHttpd 会自动在请求完毕删除掉文件 所以克隆一份WritableMap map = Arguments.createMap();map.putString("name", nameStr.get(0));map.putString("path", distFile.getPath());params.pushMap(map);str = this.readTxt(distFile.getPath());}
// 页面监听WifiServer.FILE_UPLOAD_NEW事件,接收从PC导入的数据
this.context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(WifiServer.FILE_UPLOAD_NEW, str);}private  String readTxt(String filePath) {StringBuilder result = new StringBuilder();try {BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath)), "UTF-8"));String lineTxt = null;while ((lineTxt = bfr.readLine()) != null) {result.append(lineTxt).append("\n");}bfr.close();} catch (Exception e) {e.printStackTrace();}return result.toString();}

4. 关闭本地服务

this.httpServer.stop();

以上就是手机端起简易服务器与PC端实现互传的流程,涉及到很多java文件读取的方法,我本来想使用nanohttpd的webserver解决,但是发现他只能展示页面,不好修改(它本身就是依赖nanohttpd完成的,更多信息在nanohttpd的官方文档)。读了源码也有些一知半解,最后在公司前辈的帮助下完成的该功能。

感谢阅读,有疑问请留言,我会尽我所能解答的。(要源码的就别留了)

React-Native使用Nanohttpd实现跨平台互传文件相关推荐

  1. 用电脑发短信_丢掉你的手机数据线吧!用这个软件轻松在任何设备互传文件

    在介绍了两期跨平台文件互传解决方案(请翻阅我最近的几篇文章)之后,总有些意犹未尽,因为有太多的好软件了.但是,前几期介绍的软件,侧重于文件传输.例如手机和手机,手机和电脑互传图片,文档,视频,歌曲等资 ...

  2. iphone与android传文件,安卓与苹果手机之间互传文件的方法教程

    一直以来,很多的app都是分为安卓和IOS两个版本,在使用上,两个平台之间很多功能都不能跨平台使用.比如大家在玩游戏时充值的东西,在苹果充值之后,同一个账号转到安卓手机上玩,那些东西都是不能迁移进来的 ...

  3. iphone 传android,安卓和苹果手机怎么互传文件_安卓与苹果手机之间互传文件的方法教程_3DM手游...

    一直以来,很多的app都是分为安卓和IOS两个版本,在使用上,两个平台之间很多功能都不能跨平台使用.比如大家在玩游戏时充值的东西,在苹果充值之后,同一个账号转到安卓手机上玩,那些东西都是不能迁移进来的 ...

  4. iphone android互传文件夹,堪比隔空投送!iPhone和安卓、PC互传文件的3种方法,建议收藏...

    相信用过苹果全家桶的小伙伴应该都对AirDrop(隔空投送)功能颇有好感,通过AirDrop可以很方便地将文件照片视频等传送到Mac.iPad等设备,不压缩原文件的同时,传输速度还非常快. AirDr ...

  5. iphone android互传文件夹,安卓和苹果手机怎么互传文件_安卓与苹果手机之间互传文件的方法教程_3DM手游...

    一直以来,很多的app都是分为安卓和IOS两个版本,在使用上,两个平台之间很多功能都不能跨平台使用.比如大家在玩游戏时充值的东西,在苹果充值之后,同一个账号转到安卓手机上玩,那些东西都是不能迁移进来的 ...

  6. Mac 和 Android 手机之间互传文件,这四种方法简单高效!

    在Windows上,我们常常需要用USB数据线将安卓手机连接到电脑上,然后在手机和电脑之间传输各种文件.但是这种方法对Mac电脑就不怎么起作用了.由于OS X系统的特殊性,许多用户都不知道如何顺利地将 ...

  7. CuteHttpFileServer-手机和电脑互传文件

    场景: 同局域网快传文件 方法 手机和电脑互传文件 CuteHttpFileServer/chfs是一个免费的.HTTP协议的文件共享服务器,使用浏览器可以快速访问.它具有以下特点: 单个文件,核心功 ...

  8. linux用户间文件互传,windows和linux间互传文件

    方法1:Xshell传输文件 用rz,sz命令在xshell传输文件 很好用,然后有时候想在windows和linux上传或下载某个文件,其实有个很简单的方法就是rz,sz 首先你的Ubuntu需要安 ...

  9. ios 应用和电脑共享文件夹_堪比AirDrop,苹果 iPhone与Windows电脑互传文件的三种方式...

    如果你是苹果全家桶用户,一定会对 「AirDrop(隔空投送)」 功能赞誉有加,使用 AirDrop 可以在 iPhone 与 MacBook.iPad 等设备之间快速传递照片.视频或文件. 遗憾的是 ...

  10. winxp 连接linux ftp,Linux和XP之间使用FTP互传文件

    Linux和XP之间使用FTP互传文件 发布时间:2007-09-05 00:57:57来源:红联作者:rganizati 今天第一次付诸于行动,发现其实很简单,跟我们正常的两台Windows XP系 ...

最新文章

  1. Python:Scrapy实战项目手机App抓包爬虫
  2. ASP.NET XML Web 服务的工作流解决方案
  3. 2016级算法期末上机-F.中等·AlvinZH's Fight with DDLs II
  4. Spring IOC 容器源码分析 - 余下的初始化工作
  5. 加密解密基础问题:字节数组和(16进制)字符串的相互转换
  6. PoE交换机的选择和使用注意事项介绍
  7. C++ 字符串指针与字符串数组
  8. 数据库基础知识——初始MySQL
  9. android app应用签名生成工具,android应用签名详细步骤
  10. niva mysql_Nivacat for mysql是一种第三方提供的()_学小易找答案
  11. 西威变频器avo下载调试资料_图解变频器的应用与接线,电气工程师必备
  12. 关于求极限对几个问题的思考和总结
  13. axios http错误码处理
  14. Pandas创建透视表教程
  15. python实验四_20191318实验四 《Python程序设计》实验报告
  16. 网易云课堂 计算机编程,网易云课堂教你如何学好计算机编程技术
  17. css 实现一个尖角_css实现气泡的小尖角效果
  18. 怎样两台计算机共用一台打印机,多台电脑如何共享一台打印机(图文讲解)
  19. JAVA毕业设计共享充电宝管理系统演示录像2021计算机源码+lw文档+系统+调试部署+数据库
  20. r5 5600g和5600x的区别 选哪个好

热门文章

  1. 【状压DP】状态压缩动态规划入门超详解
  2. 一个可以直接套用的行星齿轮传动比(转速比)结论
  3. 微信小程序全套使用指南
  4. python量化投资19种方法_【Python量化投资】新手资源大合集
  5. glide加载gif图不显示动画_Glide 加载gif的一些个人总结
  6. 【大数据面试宝典】 第一篇 Hadoop 面试题
  7. Tess4j的使用(识别中文)
  8. 周志华最新论文 | 深度森林:探索深度神经网络以外的方法
  9. Solaris11操作命令汇总
  10. 制作app怎么连接服务器,App制作步骤、流程有哪些?