更新记录

1.0.12(2024-02-23)

  1. 修复个别机型iOS公共响应头不生效问题

1.0.11(2024-02-18)

  1. 修复Android公共响应头问题

1.0.10(2024-02-07)

  1. 增加设置公共响应头接口
查看更多

平台兼容性

Android Android CPU类型 iOS
适用版本区间:4.4 - 14.0 armeabi-v7a:未测试,arm64-v8a:未测试,x86:未测试 适用版本区间:11 - 17

原生插件通用使用流程:

  1. 购买插件,选择该插件绑定的项目。
  2. 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包

付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择


前言

wrs-httpserver是Android、iOS搭建APP本地web service的插件,常用的场景有:

  1. app本地离线播放m3u8视频
  2. app本地浏览web网站,支持绝对路径,_www ,_doc,_documents,_downloads等相对路径需要转成本地绝对路径,下面有转换方法。

更多强大功能(get/post请求、文件上传下载等)请使用插件https://ext.dcloud.net.cn/plugin?id=13647

UTS版本https://ext.dcloud.net.cn/plugin?id=15876

功能

  • 启动http service,可配置多个web站点服务 注意:如果需要使用plus.io的API,需要配置项目的manifest.json里,把app-plus下的runmode改为liberate,具体原理参考uniapp官网

wrs-httpserver插件

场景 1. 直接访问在uniapp项目源码里的web站点


String.prototype.endWith = function(endStr) {
    var d = this.length - endStr.length;
    return (d >= 0 && this.lastIndexOf(endStr) == d)
}
var httpServer = uni.requireNativePlugin("wrs-httpserver");
// 把_www相对路径转为绝对路径
var absPath = plus.io.convertLocalFileSystemURL('_www');
// Android获取的absPath以/结尾,iOS获取的absPath不是/结尾
if (absPath.endWith('/')) {
    absPath = absPath.substring(0, absPath.length - 1);
}
var params = {
    port: 8030,  // http service的端口
    staticWebs: [
      {
        urlPath: '/register', // 站点请求的url
        directoryPath: absPath + '/static/registerSys'  // web站点文件绝对路径,这个路径是绝对路径
      },
     {
        urlPath: '/login',
        directoryPath: absPath + '/static/loginSys'
      }
    ],
    uploadFilePath: uploadFilePath // 文件上传下载路径,目前仅对iOS生效,服务启动后,通过 http://ip:端口 访问文件目录

};
httpServer.startServer(params, (resp) => {
    if (resp.code == 0) {
        console.log("httpServer启动成功:" + resp.serverHost);
    } else {
        console.log("httpServer启动失败:" + resp.msg);
    }
});

启动成功后,在浏览器输入resp.serverHost + port + urlPath + 网站文件,如:


http://192.168.6.31:8030/register/index.html
http://192.168.6.31:8030/login/index.html

loginSys、loginSys这两个站点的源码放到HBuildx项目里的static文件夹里

  • -- 项目名
  • --- static
  • ---- loginSys
  • ---- registerSys

uploadFilePath:文件上传下载管理路径,目前只支持iOS,文件管理的站点代码在demo目录iOSFileUploadWebSite文件夹

具体看右图 image.png

场景 2. 通过接口网络下载web站点源码并访问


                               // 下载web站点压缩文件
                uni.downloadFile({
                    url: "http://192.168.6.89:8080/video/registerSys.zip", //仅为示例,并非真实的资源
                    success: (res) => {
                        if (res.statusCode === 200) {
                            var zipfile = res.tempFilePath;
                                                        // 下载后的压缩文件解压到_downloads目录
                            var targetPath = '_downloads/';
                            var absPath = plus.io.convertLocalFileSystemURL(targetPath);
                            // 经测试,修正在华为Android 10的系统上解压的解压目录,Android上使用绝对路径
                            switch (uni.getSystemInfoSync().platform) {
                                case 'android':
                                    targetPath = plus.io.convertLocalFileSystemURL(targetPath);
                                    break;
                                case 'ios':
                                    targetPath = '_downloads/';
                                    break;
                                default:

                                    break;
                            }
                            plus.zip.decompress(zipfile, targetPath,
                                function() {
                                    var path = plus.io.convertLocalFileSystemURL(targetPath);
                                    console.log('解压成功绝对路径:' + path);
                                },
                                function(error) {
                                    console.log('解压解压失败:' + error);
                                });
                        } else {
                            console.log('下载失败');
                        }
                    }
                });

解压后_downloads目录已经有站点文件了,在启动http server时把_downloads下的站点也加进入即可:


                                // _www ,_doc,_documents,_downloads
                var staticWebs = [];
                var paths = ['_www', '_downloads'];
                for (var i = 0; i < paths.length; i++) {
                    var path = paths[i];
                    var absPath = plus.io.convertLocalFileSystemURL(path);
                    // Android获取的absPath以/结尾,iOS获取的absPath不是/结尾
                    if (absPath.endWith('/')) {
                        absPath = absPath.substring(0, absPath.length - 1);
                    }
                    switch (i) {
                        case 0: {
                            staticWebs.push({
                                urlPath: '/staticLoginSys',
                                directoryPath: absPath + '/static/loginSys',
                            });
                            staticWebs.push({
                                urlPath: '/',
                                directoryPath: absPath + '/static/registerSys',
                            });
                        }
                        break;
                    case 1: {
                        staticWebs.push({
                            urlPath: '/downloadsSys',
                            directoryPath: absPath + '/registerSys',
                        });
                    }
                    break;
                    default:
                        break;
                    }
                    console.log('path:' + path + '  绝对路径:' + absPath);
                }
                var appid = plus.runtime.appid;
                var params = {
                    port: 8030,
                    staticWebs: staticWebs
                };
                this.staticWebs = staticWebs;
                httpServer.startServer(params, (resp) => {
                    if (resp.code == 0) {
                        console.log("httpServer启动成功:" + resp.serverHost);
                    } else {
                        console.log("httpServer启动失败:" + resp.msg);
                    }
                });

_downloads下web站点的访问地址是:


http://192.168.6.31:8030/downloadsSys/index.html

停止http server服务


httpServer.stopServer()

判断http server服务是否在运行


var obj = httpServer.isRuning();
if(obj.isRuning) {
    console.log("httpServer服务正在运行");
} else {
    console.log("httpServer服务没有运行");
}

增加公共响应头(一般用于解决跨域问题)


var header = {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, POST, OPTIONS, DELETE, PUT",
    "Access-Control-Allow-Headers": "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,lang,access-token"
}

httpServer.setCommonResponseHeader(header)

如果Android打包时出现如下错误,请再次提交打包,这是uniapp云打包下载库没有及时下载到造成的,需要多试几次


Appid: xxx

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:checkReleaseAarMetadata'.
> Could not resolve all files for configuration ':app:releaseRuntimeClasspath'.
> Could not resolve xxx.
Required by:
project :app
> Could not resolve xxxxxxxxx.
> Could not get resource 'https://dl.google.com/dl/android/maven2/com/xxxxxx-xxxx.pom'.

完整代码


<template>
    <div>
        <text>HttpServer</text>

        <button @click="startServer">启动服务</button>
        <button @click="stopServer">暂停服务</button>
        <button @click="serverIsRunning">服务是否在运行</button>
        <button @click="downloads">下载站点</button>
        <text class="log">{{msg}}</text>
    </div>
</template>

<script>
    String.prototype.endWith = function(endStr) {
        var d = this.length - endStr.length;
        return (d >= 0 && this.lastIndexOf(endStr) == d)
    }
    var httpServer = uni.requireNativePlugin("wrs-httpserver");
    export default {
        data() {
            return {
                msg: "",
                url: "http://192.168.6.89:8080/video/registerSys.zip"
            }
        },
        methods: {
            startServer: function() {
                // _www ,_doc,_documents,_downloads
                var staticWebs = [];
                var paths = ['_www', '_downloads'];
                for (var i = 0; i < paths.length; i++) {
                    var path = paths[i];
                    var absPath = plus.io.convertLocalFileSystemURL(path);
                    // Android获取的absPath以/结尾,iOS获取的absPath不是/结尾
                    if (absPath.endWith('/')) {
                        absPath = absPath.substring(0, absPath.length - 1);
                    }
                    switch (i) {
                        // _www
                        case 0: {
                            staticWebs.push({
                                urlPath: '/staticLoginSys', // 站点请求的url
                                directoryPath: absPath + '/static/loginSys',// web站点文件绝对路径,这个路径是绝对路径
                            });
                            staticWebs.push({
                                urlPath: '/staticRegisterSys',
                                directoryPath: absPath + '/static/registerSys',
                            });
                        }
                        break;
                        // _downloads
                    case 1: {
                        staticWebs.push({
                            urlPath: '/downloadsSys',
                            directoryPath: absPath + '/registerSys',
                        });
                    }
                    break;
                    case 2: {
                        staticWebs.push({
                            urlPath: '/documentsSys',
                            directoryPath: absPath + '/registerSys',
                        });
                    }
                    break;
                    case 3: {
                        staticWebs.push({
                            urlPath: '/docSys',
                            directoryPath: absPath + '/registerSys',
                        });
                    }
                    break;
                    default:
                        break;
                    }
                    console.log('path:' + path + '  绝对路径:' + absPath);
                }
                var appid = plus.runtime.appid;
                var params = {
                    port: 8030, // 端口
                    staticWebs: staticWebs
                };
                // 启动http service
                httpServer.startServer(params, (resp) => {
                    if (resp.code == 0) {
                        console.log("httpServer启动成功:" + resp.serverHost);
                    } else {
                        console.log("httpServer启动失败:" + resp.msg);
                    }
                });
            },
            stopServer: function() {
                // 停止http server
                httpServer.stopServer();
            },
            serverIsRunning: function(){
                var obj = httpServer.isRuning();
                if(obj.isRuning) {
                    console.log("httpServer服务正在运行");
                } else {
                    console.log("httpServer服务没有运行");
                }
            },
            downloads: function() {
                uni.downloadFile({
                    url: this.url, //仅为示例,并非真实的资源
                    success: (res) => {
                        if (res.statusCode === 200) {
                            var zipfile = res.tempFilePath;
                            var targetPath = '_downloads/';
                            var absPath = plus.io.convertLocalFileSystemURL(targetPath);
                            // 经测试,修正在华为Android 10的系统上解压的解压目录,Android上使用绝对路径
                            switch (uni.getSystemInfoSync().platform) {
                                case 'android':
                                    targetPath = plus.io.convertLocalFileSystemURL(targetPath);
                                    break;
                                case 'ios':
                                    targetPath = '_downloads/';
                                    break;
                                default:
                                    break;
                            }
                            plus.zip.decompress(zipfile, targetPath,
                                function() {
                                    var path = plus.io.convertLocalFileSystemURL(targetPath);
                                    console.log('解压成功绝对路径:' + path);
                                },
                                function(error) {
                                    console.log('解压解压失败:' + error);
                                });
                        } else {
                            console.log('下载失败');
                        }
                    }
                });
            },
            showMsg: function(msg) {
                // httpServer.log({
                //     msg: msg
                // });
                this.msg = msg;
            },
            logPath: function() {
                var paths = ['_www', '_downloads', '_doc', '_documents'];
                for (var i = 0; i < paths.length; i++) {
                    var path = paths[i];
                    var absPath = plus.io.convertLocalFileSystemURL(path);
                    console.log('path:' + path + '  绝对路径:' + absPath);
                }
            }
        }
    }
</script>

组件文档:https://www.jianshu.com/p/543d28b22716

如果觉得可以就点个👍吧,欢迎粉丝收藏,土豪打赏,您的关注就是我们创作的动力!

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问