HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

mui plusReady 不触发问题。

添加。
<script src="html5plus://ready"></script>

添加。
<script src="html5plus://ready"></script>

看到网上介绍的HBuilder的介绍,下载下来尝试. 唉。

看到网上介绍的HBuilder的介绍,下载下来尝试, 装上去试下。

  1. 绿色版本,很不错啊。
    安装上去,运行,界面很简介也不错。
    提示很贴心,不必webStorm 差。

  2. 看一看内存,晕死了都。 700M. 只打开了一个文件。
    占用内存,是当时放弃webStrom的主要原因。
    唉,都是Eclipse害的。
    果断放弃HBuilder, 还是用我的sublime吧。

  3. sublime内存占用没超过 100M, 一般稳定在 60M左右,速度又快。

    现在是,只要看到 Eclipse 就不敢用啊!
    开Eclipse之类的,编译其它程序代码,立马报告 内存不足。

    公司系统加密,只能用XP, 上不了大内存啊.

继续阅读 »

看到网上介绍的HBuilder的介绍,下载下来尝试, 装上去试下。

  1. 绿色版本,很不错啊。
    安装上去,运行,界面很简介也不错。
    提示很贴心,不必webStorm 差。

  2. 看一看内存,晕死了都。 700M. 只打开了一个文件。
    占用内存,是当时放弃webStrom的主要原因。
    唉,都是Eclipse害的。
    果断放弃HBuilder, 还是用我的sublime吧。

  3. sublime内存占用没超过 100M, 一般稳定在 60M左右,速度又快。

    现在是,只要看到 Eclipse 就不敢用啊!
    开Eclipse之类的,编译其它程序代码,立马报告 内存不足。

    公司系统加密,只能用XP, 上不了大内存啊.

收起阅读 »

MUI仿咸鱼底部tabbar圆形发布按钮样式

tabbar

<nav class="mui-bar mui-bar-tab footer-nav">
<a class="mui-tab-item mui-active" href="#tabbar">
<span class="mui-icon icon">&#xe62b;</span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-chat">
<span class="mui-icon icon">&#xe602;</span>
<span class="mui-tab-label">分类</span>
</a>
<a class="mui-tab-item tab-item-center" href="#tabbar-with-contact">
<span class="mui-icon plus"><span class="icon">&#xe60d;</span></span>
<span class="mui-tab-label tab-label">发布</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-contact">
<span class="mui-icon icon">&#xe647;</span>
<span class="mui-tab-label">消息</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-map">
<span class="mui-icon icon">&#xe655;</span>
<span class="mui-tab-label">我的</span>
</a>
</nav>

.footer-nav .tab-item-center{
position:relative;
overflow:visible;
text-align:center;
}
.footer-nav .tab-item-center .plus{
display:inline-block;
width:100%;
color:#fff;
position:absolute;
left:0;
top:-25px;
}
.footer-nav .tab-item-center .plus .icon{
width:auto;
height:auto;
padding:10px;
background:#1ba9ba;
border-radius:50%;
border:3px solid #fff;
box-shadow: 0 -2px 3px rgba(100,100,100,.4);
}
.footer-nav .tab-item-center .tab-label{
margin-top:25px;
}

继续阅读 »

<nav class="mui-bar mui-bar-tab footer-nav">
<a class="mui-tab-item mui-active" href="#tabbar">
<span class="mui-icon icon">&#xe62b;</span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-chat">
<span class="mui-icon icon">&#xe602;</span>
<span class="mui-tab-label">分类</span>
</a>
<a class="mui-tab-item tab-item-center" href="#tabbar-with-contact">
<span class="mui-icon plus"><span class="icon">&#xe60d;</span></span>
<span class="mui-tab-label tab-label">发布</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-contact">
<span class="mui-icon icon">&#xe647;</span>
<span class="mui-tab-label">消息</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-map">
<span class="mui-icon icon">&#xe655;</span>
<span class="mui-tab-label">我的</span>
</a>
</nav>

.footer-nav .tab-item-center{
position:relative;
overflow:visible;
text-align:center;
}
.footer-nav .tab-item-center .plus{
display:inline-block;
width:100%;
color:#fff;
position:absolute;
left:0;
top:-25px;
}
.footer-nav .tab-item-center .plus .icon{
width:auto;
height:auto;
padding:10px;
background:#1ba9ba;
border-radius:50%;
border:3px solid #fff;
box-shadow: 0 -2px 3px rgba(100,100,100,.4);
}
.footer-nav .tab-item-center .tab-label{
margin-top:25px;
}

收起阅读 »

原生图片剪裁,利用cropper.js插件和5+的图片压缩实现,可直接输出base64或保存本地图片。

图片压缩 头像裁剪

如题。理论上完全兼容android和ios。
cropper.js应该很多人用过,是web端图片剪裁的利器。可以对图片进行base64编码,方便上传后台。
5+中的api。plus.zip.compressImage接口,压缩图片保存本地的效率很高,但是没有图形化界面。
于是,我就想 ,把这两个结合起来,做出图形化剪裁的功能来,实现本地存储和base64输出。
结果发现,天作之合,太简单了。
我想说,也许是目前最好的剪裁方案了。(不知道有没有别人提出过这个方法,我先小得意一下)

本人非专业前端,js弱鸡,不会做插件化开发。只能流水式写方法了。

不废话,直接页面代码,我把每一步都写得非常详细,再菜的人应该都能看懂了(而且确实非常简单)。
召唤这个页面的页面代码我就不放了。相信没有那么菜的鸡。

<!DOCTYPE html>  
<html>  
    <head>  
        <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no">  
        <meta name="apple-mobile-web-app-capable" content="yes">  
        <meta name="apple-mobile-web-app-status-bar-style" content="black">  
        <meta charset="utf-8">  
        <title></title>  
        <link rel="stylesheet" href="css/cropper.min.css" />  
        <link rel="stylesheet" href="css/mui.min.css" />  
        <style>  
            #redo{  
                position: fixed;  
                bottom: 20px;  
                left :20px;  
                font-size: 30px;  
                color: #FFFFFF;  
            }  
            #undo{  
                position: fixed;  
                bottom: 20px;  
                right :20px;  
                font-size: 30px;  
                color: #FFFFFF;  
            }  
            html{  
                background: #000000;  
            }  
            .holdcenter{  
                background-color: #007AFF;  
                order:auto;  
                flex: 0 1 auto;  
                -webkit-flex: 0 1 auto;  
                align-self: auto;  
                overflow: hidden;  
            }  
            .outer-box{  
                display: flex;  
                display: -webkit-flex;  
                /*height: 100%;*/  
                /*border: 1px solid #000000;*/  
                background-color: #000000;  
                flex-direction: row;  
                flex-flow: row wrap;  
                -webkit-flex-flow: row wrap;  
                /*justify-content: flex-start;*/  
               justify-content: center;  
               align-items: center;  
            }  
        </style>  
    </head>  
    <body>  
        <header class="mui-bar mui-bar-transparent">  
          <!--<h1 id="patientId" class="mui-title">截取头像</h1>-->  
          <a id="save"  class="mui-icon mui-icon-checkmarkempty mui-pull-right" style="font-size: 3rem;color: #FFFFFF;"></a>  
        </header>  
        <div style="" class="outer-box mui-fullscreen">  
            <div style="" class="holdcenter">  
                <img style="width: 100%;" id="image" src="images/cbd.jpg">  
            </div>  
            <a id="redo" class=" mui-pull-left"><span class="mui-icon mui-icon-redo"></span></a>  
            <a id="undo" class=" mui-pull-right"><span class="mui-icon mui-icon-undo"></span></a>  
        </div>  
        <script type="text/javascript" src="js/mui.min.js" ></script>  
        <script type="text/javascript" src="js/cropper.min.js" ></script>  
        <script>  
            /**  
             * 本功能灵感来源于 crooper.js。github地址请看js文件  
             * 利用cropper.js进行图片剪裁。支持旋转。  
             * 可以直接获取剪裁后的base64。  
             * 也可以利用cropper的方法,可以获取一系列参数,借用5+API,  
             * 可以直接保存本地图片,效率非常高。  
             * 有对cropper.js熟悉的可以进一步研究修改,提供更多可用功能  
             * 理论上完全兼容android和ios系统。  
             */  
            mui.init({  
                hardwareAccelerated:true,  
            });  

            var image = document.getElementById('image');//获取图片元素  
            var cropper = null;  
            var resImg = null;      //剪切后图片base64编码资源  

            //初始化控件的方法  
            function initCropper(){  
                cropper = new Cropper(image, {  
                    //aspectRatio: 1/1,16/9,4/3,2/3,NaN(自定义)  
                    aspectRatio: NaN,   //不锁定 "剪裁框" 比例(自定义)  
                    dragMode:'crop',  
                    rotatable:true, //是否允许旋转  
                    minCropBoxWidth:0,  
                    minCropBoxHeight:0,  
                    minCanvasWidth:0,  
                    minCanvasHeight:0,  
                    minContainerWidth:200,  
                    minContainerHeight:200,  
                    cropBoxResizable: true, //是否允许 调整 剪裁框 的大小  
                    crop: function(data) {  
                     }  
                });  
            }// initCropper  end  

            //保存按钮监听  
            document.getElementById("save").addEventListener("tap",function(){  
                //传入true,获取base64字串,不传或者传入false保存本地文件,获取保存路径。  
                getImg();  
            });  
            //右旋转按钮监听  
            document.getElementById("redo").addEventListener("tap",function(){  
                cropper.rotate(90);  
                //这里的旋转角度90数据可自行定义,比方说:15,30,45。支持每次旋转1度  
                //但是考虑到5+api的旋转只支持90一个单位,所以设定每次旋转90度。  
                //有兴趣可以去cropper的范列网站https://fengyuanchen.github.io/cropperjs/自己定义旋转角度试试。  
                //但是227行的5+api旋转参数如何对应需要动脑筋。90度旋转对用户来说应该足够了。  
            });  
            //左旋转按钮监听  
            document.getElementById("undo").addEventListener("tap",function(){  
                cropper.rotate(-90);  
            });  

            //在选择或者拍摄完成后打开此裁剪页面并把图片路径传递到此页面  
            mui.plusReady(function(){  
                //imgSrc是webview的扩展参数传过来的图片路径,用io方法转换成本地绝对路径  
                image.src = plus.io.convertLocalFileSystemURL(plus.webview.currentWebview().imgSrc);  
                //image.src = "images/muwu.jpg";  

                initCropper();  //初始化cropper控件  
            });//plusReady  end  

            /**  
             * 获取图片的方法  
             * @param {Boolean} flag  
             */  
            function getImg(flag){  
                //如果flag传入true,生成base64资源     

                if(flag){  
                    resImg =  cropper.getCroppedCanvas({  
                          width: 300,  
                          height: 300  
                    }).toDataURL();  
                    //纯cropper.js的功能  
                    //resImg 就是base64字符串,可以返回给需要的页面或者上传  
                    console.log(resImg);  
                    //like is “data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAFkCAYAAACadgZ0AAAgAElEQVR4XtS9”  
                }else{  
                //否则生成本地图片  
                    //cropper提供的方法,可以获取剪裁范围内的图片的信息,这一个方法就够了。下面的其他方法仅供参考  
                    var cropeddata = cropper.getData();               
                    //console.log(JSON.stringify(cropeddata));  
                    /* 像这样  
                     * {"x":793.6,      /左边距,像素,单位px  
                     * "y":297.59999999999997,  //上边距  
                    *   "width":2380.7999999999997,     //选中的部分图片的宽度,px,Number  
                    *   "height":2380.7999999999997,    //选中部分图片的高度,px,Number  
                    *   "rotate":0,                     //旋转度数,Number  
                    *   "scaleX":1,                     //x轴缩放比例Number  
                    *   "scaleY":1}                     //y轴缩放比例Number  
                    */  

                    //原始图片信息  
                    var sourceImgDate = cropper.getImageData();  
                    //console.log(JSON.stringify(sourceImgDate));  
                    /* 像这样  
                     * {"naturalWidth":3968,        //原始图片宽度,px,像素  
                        "naturalHeight":2976,       //原始图片高度,px  
                        "aspectRatio":1.3333333333333333,   //纵横比,高宽比  
                        "width":360,                        //在页面上的显示尺寸  
                        "height":270,  
                        "left":0,  
                        "top":0}  
                     */  

                    //获取容器(img元素)的信息  
                    var containerData = cropper.getContainerData();  
                    //console.log(JSON.stringify(containerData));  
                    /*  像这样  
                     * {"width":360,"height":276}  
                     */  

                    //剪裁框的信息  
                    var cropData = cropper.getCropBoxData();  
                    //console.log(JSON.stringify(cropData));  
                    /*  像这样  
                     * {"left":72,"top":30,  
                     *  "width":216,  
                     * "height":216}  
                     */  

                    //获取canvers的信息  
                    var canversData = cropper.getCanvasData();  
                    //console.log(JSON.stringify(canversData));  
                    /*  像这样  
                     * {"left":0,"top":3,  
                     * "width":360,  
                     * "height":270,  
                     * "naturalWidth":3968,  
                     * "naturalHeight":2976}  
                     */  

                    //接下来使用H5+的图片压缩压缩转换API来完成剪裁和压缩  
                    //http://www.html5plus.org/doc/zh_cn/zip.html  
                    //准备工作  
                    //JSON对象,图片裁剪区域的参数  
                    //注意:4个属性我们都已经通过cropper的getData()方法直接获取到了值,是不是很简单呢  
                    //直接组织数据吧  
                    var ClipImageOptions = {  
                        top:cropeddata.y ,      //(String 类型 )图片裁剪区域与原图片上边界的偏移距离  
                                    //支持像素值(如"10px")、百分比(如"10%");默认值为"0px"。 注意:如果top值超出原图片高度,则图片裁剪失败。  

                        left:cropeddata.x ,     //(Stirng 类型 )图片裁剪区域与原图片左边界的偏移距离  
                                    //支持像素值(如"10px")、百分比(如"10%");默认值为"0px"。 注意:如果left值超出原图片宽度,则图片裁剪失败。  

                        width:cropeddata.width,         //(String 类型 )图片裁剪区域的宽度  
                                    //支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即从left位置到图片右边界的宽度);默认值为"auto"。 注意:如果left值加width值超出原图片宽度,则使用"auto"值进行裁剪。  

                        height:cropeddata.height    //(String 类型 )图片裁剪区域的高度  
                                    //支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即从top位置到图片下边界的高度);默认值为"auto"。 注意:如果top值加height值超出原图片高度,则使用"auto"值进行裁剪。  
                    }  

                    //处理旋转角度,因为5+api不接受负值  
                    var rotate = 0;//默认值  
                    if(cropeddata.rotate >= 0){  
                        rotate = cropeddata.rotate;  
                    }else{  
                        switch(cropeddata.rotate){  
                            case -90:  
                                rotate = 270;  
                                break;  
                            case -180:  
                                rotate = 180;  
                                break;  
                            case -270:  
                                rotate = 90;  
                                break;  
                            default:  
                                rotate = 0;   
                        }  
                    }  

                    //获取图片格式                  
                    var format = image.src.substring(image.src.lastIndexOf(".")+1);  
                    //console.log(format);  
                    //根据日期生成图片名称  
                    var d = new Date();                   
                    var picName = d.getFullYear()+""+(d.getMonth()+1)+""+d.getDate()+""+d.getHours()+""+d.getMinutes()+""+d.getSeconds();  
                    var fullname = picName+"."+format;  
                    console.log(fullname); //完整图片名称  

                    //JSON对象,配置图片压缩转换的参数  
                    var imgOption = {src:image.src,     //原始图片路径  
                        dst: "../doc/"+fullname ,//(String 类型 )压缩转换目标图片的路径,这里保存到 私有目录doc  
                                                    //如“/sdcard/Android/data/io.dcloud.HBuilder/.HBuilder/apps/HBuilder/doc”。  
                        overwrite:true,     //覆盖生成新文件  
                        format: '',//(String 类型 )压缩转换后的图片格式,支持"jpg"、"png",如果未指定则使用源图片的格式。  
                        quality:50,//(Number 类型 )压缩图片的质量,可以自己调整  
                                        //取值范围为1-100,1表示使用最低的图片质量(转换后的图片文件最小)、100表示使用最高的图片质量(转换后的图片文件最大); 默认值为50。  
                        width:'auto',       //(String 类型 )缩放图片的宽度  
                                    //支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据height与源图高的缩放比例计算,若未设置height则使用源图高度); 默认值为"auto"。 注意:若设置了width属性值不合法(如"0px"),则不对图片进行缩放操作。  

                        height:'auto',  //(String 类型 )缩放图片的高度  
                                        //支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据width与源图宽的缩放比例计算,若未设置width则使用源图高度); 默认值为"auto"。 注意:若设置了height属性值不合法(如"0px"),则不对图片进行缩放操作。  

                        rotate:rotate,      //(Number 类型 )旋转图片的角度  
                                        //支持值:90-表示旋转90度;180-表示旋转180度;270-表示旋转270度。 注意:若设置rotate属性值不合法,则不对图片进行旋转操作。  
                        clip: ClipImageOptions          //(ClipImageOptions 类型(json对象) )裁剪图片的区域  
                                        //值参考ClipImageOptions定义,若设置clip属性值不合法,则不对图片进行裁剪操作。  
                    }  

                    //开始剪裁  
                    plus.zip.compressImage(  
                            imgOption,      //JSON对象,配置图片压缩转换的参数  
                            function(){                                                                           
                                //console.log(imgOption.dst);                         
                                //console.log("压缩成功");  
                                mui.toast("图片已保存到:"+imgOption.dst,{duration:"long"});  
                                //如果想要绝对路径  
                                var path=plus.io.convertLocalFileSystemURL(imgOption.dst);  
                                console.log(path);  
                                //后续处理  
                                //将imgOption.dst或者path传递给父页面,用来显示或者上传后台,请自行决定  
                                //mui.fire(plus.webview.currentWebview().opener(),"avart",{img:imgOption.dst});  
                            },function(error){                        
                                console.log("压缩失败");  

                            }  
                        );  

                    //如果不是存到doc目录,而是其他比较复杂的目录,比如根目录  
                    //用下面的方法。替换plus.io.PRIVATE_DOC就可以  
                    /*plus.io.requestFileSystem(plus.io.PRIVATE_DOC,function(fs){  
                        var filepath = fs.root.fullPath;  
                        //console.log(fs.root.fullPath);  
                        var directEntery = fs.root;  
                        //创建目录,其实这一段并不是必须的,  
                        //plus.zip.compressImage自己会创建文件夹  
                        //相对目录你可以在上面imgOption.dst里面直接写上相对路径"../doc"+fullname  
                        directEntery.getDirectory(  
                                filepath,  
                                {create:true,exclusive:false},  
                                function(direnter){  
                                    //如果文件夹已经存在,也会进入这里,所以就不用toast显示了  
                                    //mui.toast("创建doc文件夹成功");  
                                },function(e){  
                                    mui.toast("创建文件夹失败:"+e.message);  
                                    mui.back();  
                                }  
                        );  

                        //把目标路径更新到json对象  
                        imgOption.dst = filepath+fullname;  
                        //开始压缩图片  
                        plus.zip.compressImage(imgOption,  
                            function(){                                                                           
                                //console.log(imgOption.dst);                         
                                //console.log("压缩成功");  
                                mui.toast("图片已保存到:"+imgOption.dst,{duration:long});  
                                //将imgOption.dst传递给父页面,用来显示或者上传后台  
                            },function(error){                        
                                console.log("压缩失败");  

                        });  
                    }); */  

                }  

                //最后退出剪裁页面  
                mui.back();  
            }         

        </script>  
    </body>  
</html>
继续阅读 »

如题。理论上完全兼容android和ios。
cropper.js应该很多人用过,是web端图片剪裁的利器。可以对图片进行base64编码,方便上传后台。
5+中的api。plus.zip.compressImage接口,压缩图片保存本地的效率很高,但是没有图形化界面。
于是,我就想 ,把这两个结合起来,做出图形化剪裁的功能来,实现本地存储和base64输出。
结果发现,天作之合,太简单了。
我想说,也许是目前最好的剪裁方案了。(不知道有没有别人提出过这个方法,我先小得意一下)

本人非专业前端,js弱鸡,不会做插件化开发。只能流水式写方法了。

不废话,直接页面代码,我把每一步都写得非常详细,再菜的人应该都能看懂了(而且确实非常简单)。
召唤这个页面的页面代码我就不放了。相信没有那么菜的鸡。

<!DOCTYPE html>  
<html>  
    <head>  
        <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no">  
        <meta name="apple-mobile-web-app-capable" content="yes">  
        <meta name="apple-mobile-web-app-status-bar-style" content="black">  
        <meta charset="utf-8">  
        <title></title>  
        <link rel="stylesheet" href="css/cropper.min.css" />  
        <link rel="stylesheet" href="css/mui.min.css" />  
        <style>  
            #redo{  
                position: fixed;  
                bottom: 20px;  
                left :20px;  
                font-size: 30px;  
                color: #FFFFFF;  
            }  
            #undo{  
                position: fixed;  
                bottom: 20px;  
                right :20px;  
                font-size: 30px;  
                color: #FFFFFF;  
            }  
            html{  
                background: #000000;  
            }  
            .holdcenter{  
                background-color: #007AFF;  
                order:auto;  
                flex: 0 1 auto;  
                -webkit-flex: 0 1 auto;  
                align-self: auto;  
                overflow: hidden;  
            }  
            .outer-box{  
                display: flex;  
                display: -webkit-flex;  
                /*height: 100%;*/  
                /*border: 1px solid #000000;*/  
                background-color: #000000;  
                flex-direction: row;  
                flex-flow: row wrap;  
                -webkit-flex-flow: row wrap;  
                /*justify-content: flex-start;*/  
               justify-content: center;  
               align-items: center;  
            }  
        </style>  
    </head>  
    <body>  
        <header class="mui-bar mui-bar-transparent">  
          <!--<h1 id="patientId" class="mui-title">截取头像</h1>-->  
          <a id="save"  class="mui-icon mui-icon-checkmarkempty mui-pull-right" style="font-size: 3rem;color: #FFFFFF;"></a>  
        </header>  
        <div style="" class="outer-box mui-fullscreen">  
            <div style="" class="holdcenter">  
                <img style="width: 100%;" id="image" src="images/cbd.jpg">  
            </div>  
            <a id="redo" class=" mui-pull-left"><span class="mui-icon mui-icon-redo"></span></a>  
            <a id="undo" class=" mui-pull-right"><span class="mui-icon mui-icon-undo"></span></a>  
        </div>  
        <script type="text/javascript" src="js/mui.min.js" ></script>  
        <script type="text/javascript" src="js/cropper.min.js" ></script>  
        <script>  
            /**  
             * 本功能灵感来源于 crooper.js。github地址请看js文件  
             * 利用cropper.js进行图片剪裁。支持旋转。  
             * 可以直接获取剪裁后的base64。  
             * 也可以利用cropper的方法,可以获取一系列参数,借用5+API,  
             * 可以直接保存本地图片,效率非常高。  
             * 有对cropper.js熟悉的可以进一步研究修改,提供更多可用功能  
             * 理论上完全兼容android和ios系统。  
             */  
            mui.init({  
                hardwareAccelerated:true,  
            });  

            var image = document.getElementById('image');//获取图片元素  
            var cropper = null;  
            var resImg = null;      //剪切后图片base64编码资源  

            //初始化控件的方法  
            function initCropper(){  
                cropper = new Cropper(image, {  
                    //aspectRatio: 1/1,16/9,4/3,2/3,NaN(自定义)  
                    aspectRatio: NaN,   //不锁定 "剪裁框" 比例(自定义)  
                    dragMode:'crop',  
                    rotatable:true, //是否允许旋转  
                    minCropBoxWidth:0,  
                    minCropBoxHeight:0,  
                    minCanvasWidth:0,  
                    minCanvasHeight:0,  
                    minContainerWidth:200,  
                    minContainerHeight:200,  
                    cropBoxResizable: true, //是否允许 调整 剪裁框 的大小  
                    crop: function(data) {  
                     }  
                });  
            }// initCropper  end  

            //保存按钮监听  
            document.getElementById("save").addEventListener("tap",function(){  
                //传入true,获取base64字串,不传或者传入false保存本地文件,获取保存路径。  
                getImg();  
            });  
            //右旋转按钮监听  
            document.getElementById("redo").addEventListener("tap",function(){  
                cropper.rotate(90);  
                //这里的旋转角度90数据可自行定义,比方说:15,30,45。支持每次旋转1度  
                //但是考虑到5+api的旋转只支持90一个单位,所以设定每次旋转90度。  
                //有兴趣可以去cropper的范列网站https://fengyuanchen.github.io/cropperjs/自己定义旋转角度试试。  
                //但是227行的5+api旋转参数如何对应需要动脑筋。90度旋转对用户来说应该足够了。  
            });  
            //左旋转按钮监听  
            document.getElementById("undo").addEventListener("tap",function(){  
                cropper.rotate(-90);  
            });  

            //在选择或者拍摄完成后打开此裁剪页面并把图片路径传递到此页面  
            mui.plusReady(function(){  
                //imgSrc是webview的扩展参数传过来的图片路径,用io方法转换成本地绝对路径  
                image.src = plus.io.convertLocalFileSystemURL(plus.webview.currentWebview().imgSrc);  
                //image.src = "images/muwu.jpg";  

                initCropper();  //初始化cropper控件  
            });//plusReady  end  

            /**  
             * 获取图片的方法  
             * @param {Boolean} flag  
             */  
            function getImg(flag){  
                //如果flag传入true,生成base64资源     

                if(flag){  
                    resImg =  cropper.getCroppedCanvas({  
                          width: 300,  
                          height: 300  
                    }).toDataURL();  
                    //纯cropper.js的功能  
                    //resImg 就是base64字符串,可以返回给需要的页面或者上传  
                    console.log(resImg);  
                    //like is “data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAFkCAYAAACadgZ0AAAgAElEQVR4XtS9”  
                }else{  
                //否则生成本地图片  
                    //cropper提供的方法,可以获取剪裁范围内的图片的信息,这一个方法就够了。下面的其他方法仅供参考  
                    var cropeddata = cropper.getData();               
                    //console.log(JSON.stringify(cropeddata));  
                    /* 像这样  
                     * {"x":793.6,      /左边距,像素,单位px  
                     * "y":297.59999999999997,  //上边距  
                    *   "width":2380.7999999999997,     //选中的部分图片的宽度,px,Number  
                    *   "height":2380.7999999999997,    //选中部分图片的高度,px,Number  
                    *   "rotate":0,                     //旋转度数,Number  
                    *   "scaleX":1,                     //x轴缩放比例Number  
                    *   "scaleY":1}                     //y轴缩放比例Number  
                    */  

                    //原始图片信息  
                    var sourceImgDate = cropper.getImageData();  
                    //console.log(JSON.stringify(sourceImgDate));  
                    /* 像这样  
                     * {"naturalWidth":3968,        //原始图片宽度,px,像素  
                        "naturalHeight":2976,       //原始图片高度,px  
                        "aspectRatio":1.3333333333333333,   //纵横比,高宽比  
                        "width":360,                        //在页面上的显示尺寸  
                        "height":270,  
                        "left":0,  
                        "top":0}  
                     */  

                    //获取容器(img元素)的信息  
                    var containerData = cropper.getContainerData();  
                    //console.log(JSON.stringify(containerData));  
                    /*  像这样  
                     * {"width":360,"height":276}  
                     */  

                    //剪裁框的信息  
                    var cropData = cropper.getCropBoxData();  
                    //console.log(JSON.stringify(cropData));  
                    /*  像这样  
                     * {"left":72,"top":30,  
                     *  "width":216,  
                     * "height":216}  
                     */  

                    //获取canvers的信息  
                    var canversData = cropper.getCanvasData();  
                    //console.log(JSON.stringify(canversData));  
                    /*  像这样  
                     * {"left":0,"top":3,  
                     * "width":360,  
                     * "height":270,  
                     * "naturalWidth":3968,  
                     * "naturalHeight":2976}  
                     */  

                    //接下来使用H5+的图片压缩压缩转换API来完成剪裁和压缩  
                    //http://www.html5plus.org/doc/zh_cn/zip.html  
                    //准备工作  
                    //JSON对象,图片裁剪区域的参数  
                    //注意:4个属性我们都已经通过cropper的getData()方法直接获取到了值,是不是很简单呢  
                    //直接组织数据吧  
                    var ClipImageOptions = {  
                        top:cropeddata.y ,      //(String 类型 )图片裁剪区域与原图片上边界的偏移距离  
                                    //支持像素值(如"10px")、百分比(如"10%");默认值为"0px"。 注意:如果top值超出原图片高度,则图片裁剪失败。  

                        left:cropeddata.x ,     //(Stirng 类型 )图片裁剪区域与原图片左边界的偏移距离  
                                    //支持像素值(如"10px")、百分比(如"10%");默认值为"0px"。 注意:如果left值超出原图片宽度,则图片裁剪失败。  

                        width:cropeddata.width,         //(String 类型 )图片裁剪区域的宽度  
                                    //支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即从left位置到图片右边界的宽度);默认值为"auto"。 注意:如果left值加width值超出原图片宽度,则使用"auto"值进行裁剪。  

                        height:cropeddata.height    //(String 类型 )图片裁剪区域的高度  
                                    //支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即从top位置到图片下边界的高度);默认值为"auto"。 注意:如果top值加height值超出原图片高度,则使用"auto"值进行裁剪。  
                    }  

                    //处理旋转角度,因为5+api不接受负值  
                    var rotate = 0;//默认值  
                    if(cropeddata.rotate >= 0){  
                        rotate = cropeddata.rotate;  
                    }else{  
                        switch(cropeddata.rotate){  
                            case -90:  
                                rotate = 270;  
                                break;  
                            case -180:  
                                rotate = 180;  
                                break;  
                            case -270:  
                                rotate = 90;  
                                break;  
                            default:  
                                rotate = 0;   
                        }  
                    }  

                    //获取图片格式                  
                    var format = image.src.substring(image.src.lastIndexOf(".")+1);  
                    //console.log(format);  
                    //根据日期生成图片名称  
                    var d = new Date();                   
                    var picName = d.getFullYear()+""+(d.getMonth()+1)+""+d.getDate()+""+d.getHours()+""+d.getMinutes()+""+d.getSeconds();  
                    var fullname = picName+"."+format;  
                    console.log(fullname); //完整图片名称  

                    //JSON对象,配置图片压缩转换的参数  
                    var imgOption = {src:image.src,     //原始图片路径  
                        dst: "../doc/"+fullname ,//(String 类型 )压缩转换目标图片的路径,这里保存到 私有目录doc  
                                                    //如“/sdcard/Android/data/io.dcloud.HBuilder/.HBuilder/apps/HBuilder/doc”。  
                        overwrite:true,     //覆盖生成新文件  
                        format: '',//(String 类型 )压缩转换后的图片格式,支持"jpg"、"png",如果未指定则使用源图片的格式。  
                        quality:50,//(Number 类型 )压缩图片的质量,可以自己调整  
                                        //取值范围为1-100,1表示使用最低的图片质量(转换后的图片文件最小)、100表示使用最高的图片质量(转换后的图片文件最大); 默认值为50。  
                        width:'auto',       //(String 类型 )缩放图片的宽度  
                                    //支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据height与源图高的缩放比例计算,若未设置height则使用源图高度); 默认值为"auto"。 注意:若设置了width属性值不合法(如"0px"),则不对图片进行缩放操作。  

                        height:'auto',  //(String 类型 )缩放图片的高度  
                                        //支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据width与源图宽的缩放比例计算,若未设置width则使用源图高度); 默认值为"auto"。 注意:若设置了height属性值不合法(如"0px"),则不对图片进行缩放操作。  

                        rotate:rotate,      //(Number 类型 )旋转图片的角度  
                                        //支持值:90-表示旋转90度;180-表示旋转180度;270-表示旋转270度。 注意:若设置rotate属性值不合法,则不对图片进行旋转操作。  
                        clip: ClipImageOptions          //(ClipImageOptions 类型(json对象) )裁剪图片的区域  
                                        //值参考ClipImageOptions定义,若设置clip属性值不合法,则不对图片进行裁剪操作。  
                    }  

                    //开始剪裁  
                    plus.zip.compressImage(  
                            imgOption,      //JSON对象,配置图片压缩转换的参数  
                            function(){                                                                           
                                //console.log(imgOption.dst);                         
                                //console.log("压缩成功");  
                                mui.toast("图片已保存到:"+imgOption.dst,{duration:"long"});  
                                //如果想要绝对路径  
                                var path=plus.io.convertLocalFileSystemURL(imgOption.dst);  
                                console.log(path);  
                                //后续处理  
                                //将imgOption.dst或者path传递给父页面,用来显示或者上传后台,请自行决定  
                                //mui.fire(plus.webview.currentWebview().opener(),"avart",{img:imgOption.dst});  
                            },function(error){                        
                                console.log("压缩失败");  

                            }  
                        );  

                    //如果不是存到doc目录,而是其他比较复杂的目录,比如根目录  
                    //用下面的方法。替换plus.io.PRIVATE_DOC就可以  
                    /*plus.io.requestFileSystem(plus.io.PRIVATE_DOC,function(fs){  
                        var filepath = fs.root.fullPath;  
                        //console.log(fs.root.fullPath);  
                        var directEntery = fs.root;  
                        //创建目录,其实这一段并不是必须的,  
                        //plus.zip.compressImage自己会创建文件夹  
                        //相对目录你可以在上面imgOption.dst里面直接写上相对路径"../doc"+fullname  
                        directEntery.getDirectory(  
                                filepath,  
                                {create:true,exclusive:false},  
                                function(direnter){  
                                    //如果文件夹已经存在,也会进入这里,所以就不用toast显示了  
                                    //mui.toast("创建doc文件夹成功");  
                                },function(e){  
                                    mui.toast("创建文件夹失败:"+e.message);  
                                    mui.back();  
                                }  
                        );  

                        //把目标路径更新到json对象  
                        imgOption.dst = filepath+fullname;  
                        //开始压缩图片  
                        plus.zip.compressImage(imgOption,  
                            function(){                                                                           
                                //console.log(imgOption.dst);                         
                                //console.log("压缩成功");  
                                mui.toast("图片已保存到:"+imgOption.dst,{duration:long});  
                                //将imgOption.dst传递给父页面,用来显示或者上传后台  
                            },function(error){                        
                                console.log("压缩失败");  

                        });  
                    }); */  

                }  

                //最后退出剪裁页面  
                mui.back();  
            }         

        </script>  
    </body>  
</html>
收起阅读 »

整理了一下Mdui,丰富一下Mui的样式

mui

个人觉得Mui的样式不太美观,因此我整理另一款优秀的UI框架Mdui,和Mui可以无缝对接,话不多说,直接上github地址:
https://github.com/BysunLin/Mgui

我不是代码的创造者,我只是搬运工,不过里面也加入了一些我工作中的一些积累,期望可以对入坑的同学有一点点帮助。
tips:如果能顺手加个星那就更好啦!

继续阅读 »

个人觉得Mui的样式不太美观,因此我整理另一款优秀的UI框架Mdui,和Mui可以无缝对接,话不多说,直接上github地址:
https://github.com/BysunLin/Mgui

我不是代码的创造者,我只是搬运工,不过里面也加入了一些我工作中的一些积累,期望可以对入坑的同学有一点点帮助。
tips:如果能顺手加个星那就更好啦!

收起阅读 »

android离线打包6.0以上的权限动态申请

App离线打包 权限 Android

页面调用

// android6.0以上权限申请   
function requestAndroidPremission(requestCode, func){  
    if(!permissionUtils){  
        permissionUtils = plus.android.newObject("com.build.canteen.util.PermissionUtils");  
    }  
    requestAndroidPremissionCallBack = function(requestCode){  
        if(typeof func == 'function'){  
            func(requestCode);  
        }  
    }  
    // 实现原生接口com.build.canteen.util.PermissionUtils.RequestWebViewPremissionListener对象  
    var hevent = plus.android.implements( "com.build.canteen.util.PermissionUtils$RequestWebViewPremissionListener", {  
        "requestPremissionCallBack":function(requestCode){  
            requestAndroidPremissionCallBack(requestCode)  
//          console.log( "Invoked Object’s name: "+name ); // 输出“Invoked Object’s name: Tester”  
        }  
    });  
    plus.android.invoke(permissionUtils,'setRequestWebViewPremissionListener',hevent);  
    plus.android.invoke(permissionUtils,"requestWebViewPremission",requestCode,'requestAndroidPremissionCallBack');  
}

android原生代码片段:

    // mui 动态权限申请代码  ↓↓↓↓↓↓↓↓↓↓↓↓  
    //底层隐藏的自定义Activity,重写onRequestPermissionsResult  
    private static MainActivity mActivity;  
    //由webview中的js实现此接口,用于权限申请完成后的回调webview的js函数  
    private RequestWebViewPremissionListener requestWebViewPremissionListener;  

    public static void setMainActivity(MainActivity aty){  
        mActivity = aty;  
    }  

    public void setRequestWebViewPremissionListener(RequestWebViewPremissionListener requestWebViewPremissionListener){  
        this.requestWebViewPremissionListener = requestWebViewPremissionListener;  
    }  

    public interface RequestWebViewPremissionListener{  
        void requestPremissionCallBack(int requestCode);  
    }  

    //mui调用此方法申请权限  
    public void requestWebViewPremission(int requestCode){  
        if(mActivity != null  && Build.VERSION.SDK_INT >= 23){  
            //在Activity中的onRequestPermissionsResult方法被调用  
            PermissionGrant permissionGrant = new PermissionUtils.PermissionGrant() {  
                @Override  
                public void onPermissionGranted(int requestCode) {  
                    if(requestWebViewPremissionListener!=null){  
                        requestWebViewPremissionListener.requestPremissionCallBack(requestCode);  
                    }  
                }  
            };  
            mActivity.setPermissionGrant(permissionGrant);  
            //安卓原生实现的权限申请  
            requestPermission(mActivity,requestCode,permissionGrant);  
        }else if(Build.VERSION.SDK_INT < 23){  
            if(requestWebViewPremissionListener!=null){  
                requestWebViewPremissionListener.requestPremissionCallBack(requestCode);  
            }  
        }else{  
            Log.w(TAG,"WebView  requestWebViewPremission error ,安卓运行版本:"+Build.VERSION.SDK_INT);  
        }  
    }  
    // mui 动态权限申请代码  ↑↑↑↑↑↑↑↑
写的比较粗糙,还望大神指导!
继续阅读 »

页面调用

// android6.0以上权限申请   
function requestAndroidPremission(requestCode, func){  
    if(!permissionUtils){  
        permissionUtils = plus.android.newObject("com.build.canteen.util.PermissionUtils");  
    }  
    requestAndroidPremissionCallBack = function(requestCode){  
        if(typeof func == 'function'){  
            func(requestCode);  
        }  
    }  
    // 实现原生接口com.build.canteen.util.PermissionUtils.RequestWebViewPremissionListener对象  
    var hevent = plus.android.implements( "com.build.canteen.util.PermissionUtils$RequestWebViewPremissionListener", {  
        "requestPremissionCallBack":function(requestCode){  
            requestAndroidPremissionCallBack(requestCode)  
//          console.log( "Invoked Object’s name: "+name ); // 输出“Invoked Object’s name: Tester”  
        }  
    });  
    plus.android.invoke(permissionUtils,'setRequestWebViewPremissionListener',hevent);  
    plus.android.invoke(permissionUtils,"requestWebViewPremission",requestCode,'requestAndroidPremissionCallBack');  
}

android原生代码片段:

    // mui 动态权限申请代码  ↓↓↓↓↓↓↓↓↓↓↓↓  
    //底层隐藏的自定义Activity,重写onRequestPermissionsResult  
    private static MainActivity mActivity;  
    //由webview中的js实现此接口,用于权限申请完成后的回调webview的js函数  
    private RequestWebViewPremissionListener requestWebViewPremissionListener;  

    public static void setMainActivity(MainActivity aty){  
        mActivity = aty;  
    }  

    public void setRequestWebViewPremissionListener(RequestWebViewPremissionListener requestWebViewPremissionListener){  
        this.requestWebViewPremissionListener = requestWebViewPremissionListener;  
    }  

    public interface RequestWebViewPremissionListener{  
        void requestPremissionCallBack(int requestCode);  
    }  

    //mui调用此方法申请权限  
    public void requestWebViewPremission(int requestCode){  
        if(mActivity != null  && Build.VERSION.SDK_INT >= 23){  
            //在Activity中的onRequestPermissionsResult方法被调用  
            PermissionGrant permissionGrant = new PermissionUtils.PermissionGrant() {  
                @Override  
                public void onPermissionGranted(int requestCode) {  
                    if(requestWebViewPremissionListener!=null){  
                        requestWebViewPremissionListener.requestPremissionCallBack(requestCode);  
                    }  
                }  
            };  
            mActivity.setPermissionGrant(permissionGrant);  
            //安卓原生实现的权限申请  
            requestPermission(mActivity,requestCode,permissionGrant);  
        }else if(Build.VERSION.SDK_INT < 23){  
            if(requestWebViewPremissionListener!=null){  
                requestWebViewPremissionListener.requestPremissionCallBack(requestCode);  
            }  
        }else{  
            Log.w(TAG,"WebView  requestWebViewPremission error ,安卓运行版本:"+Build.VERSION.SDK_INT);  
        }  
    }  
    // mui 动态权限申请代码  ↑↑↑↑↑↑↑↑
写的比较粗糙,还望大神指导!
收起阅读 »

福利!原生tabbar代码分享

tabbar

由于众所周知的原因,html写的tabbar十分卡顿,一直在寻求更高效的解决方案(用户才不管什么情怀不情怀,只认性能)

现在分享用js调用原生画tabbar的功能,看附件.

一来分享给大家,少走弯路;二来给自己做个备份.

由于众所周知的原因,html写的tabbar十分卡顿,一直在寻求更高效的解决方案(用户才不管什么情怀不情怀,只认性能)

现在分享用js调用原生画tabbar的功能,看附件.

一来分享给大家,少走弯路;二来给自己做个备份.

求混合开发 需要把geturl获取到的地址传到php数据库

需要把geturl获取到的地址传到php数据库
function getURL() {

alert( "页面地址为:"+embed.getURL() );

}
把上面这段代码获取到的url发送到PHP的数据库 现在页面有用户ID的变量 变量已经赋值好 用户登陆以后就能得到用户ID 把获取到的URL 发送到数据库的url字段保存到对应的用户下即可 有能做的大神联系 QQ95026686

继续阅读 »

需要把geturl获取到的地址传到php数据库
function getURL() {

alert( "页面地址为:"+embed.getURL() );

}
把上面这段代码获取到的url发送到PHP的数据库 现在页面有用户ID的变量 变量已经赋值好 用户登陆以后就能得到用户ID 把获取到的URL 发送到数据库的url字段保存到对应的用户下即可 有能做的大神联系 QQ95026686

收起阅读 »

MUI 用了这么久感觉没有一个单独的文档来说明各种mui的css类

更新MUI

MUI 用了这么久感觉没有一个单独的文档来说明各种mui的css类,都是在文档中偶尔夹杂进行点说明,或者是我太笨没发现。比如:mui-action-menu是干什么的,mui-bar我知道是标题栏的,加上它后标栏就置顶不会动了,还有很多MUI的CSS类不知道怎么用,也不知道是什么意思。或者在MUI 文档加个搜索功能,一个一个点开来用浏览器搜也比较麻烦。

继续阅读 »

MUI 用了这么久感觉没有一个单独的文档来说明各种mui的css类,都是在文档中偶尔夹杂进行点说明,或者是我太笨没发现。比如:mui-action-menu是干什么的,mui-bar我知道是标题栏的,加上它后标栏就置顶不会动了,还有很多MUI的CSS类不知道怎么用,也不知道是什么意思。或者在MUI 文档加个搜索功能,一个一个点开来用浏览器搜也比较麻烦。

收起阅读 »

android 单个大文件断点续传

最近公司项目需求做大文件的单点续传

分享下

java类代码

后台异步切割文件 切完返回true

/**  
     * 切割文件保存到指定目录 根据指定名称保存   
     * @param pWebview  
     * @param array  
     */  
    public void cutFile(final IWebview pWebview, JSONArray array){  
        final String CallBackID = array.optString(0);  
        final String filePath = array.optString(2);  
        final String cutPath = array.optString(3);  

        AsyncTask<String, Void, String> execute = new AsyncTask<String, Void, String>() {  
            public void execute(String taskId, String filePath, String cutPath) {  
            }  

            @Override  
            protected String doInBackground(String... params) {  
                java.net.HttpURLConnection connection = null;  

                byte[] buffer = new byte[readStep];  
                FileInputStream file = null;  
                File f =new File(filePath);  
                String fileName=f.getName();  
                try {  
                    file = new FileInputStream(filePath);  
                    int len = 0;  
                    int AllLen = 0;  
                    try {  
                        FileInputStream fs = new FileInputStream(filePath);  
                        fileSize = fs.available();  
                        AllLen = fileSize / (readStep);  
                        if(fileSize % (readStep) > 0){  
                            AllLen++;  
                        }  
                    } catch (IOException e) {  
                        // TODO Auto-generated catch block  
                        e.printStackTrace();  
                    }  
                    int nowCount = 1;  
                    while ((len = file.read(buffer)) > 0) {  
                        String strFilePath = cutPath+fileName+".part";  
                        try {  
                            File cutfile = new File(strFilePath);  
                            if (!cutfile.exists()) {  
                                Log.e("TestFile", "Create the file:" + strFilePath);  
                                cutfile.getParentFile().mkdirs();  
                                cutfile.createNewFile();  
                            }  
                            RandomAccessFile raf = new RandomAccessFile(cutfile, "rwd");  
                            raf.seek(0);  
                            raf.write(buffer,0,(int)len);  
                            raf.close();  
                        } catch (Exception e) {  
                            Log.e("TestFile", "Error on write File:" + e);  
                        }  
                        nowCount++;  
                    };  
                } catch (FileNotFoundException e) {  
                    e.printStackTrace();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  

                return "abc";  
            }  

            protected void onPostExecute(String result) {  
                Log.e("result",result);  
                if(result == "abc"){  
                    JSONArray newArray = new JSONArray();  
                    newArray.put(true);  
                    JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, true);  
                }  

            }  

        }.execute();  

    }

后台异步提交文件夹中所有文件碎片

/**  
     *  
     * @param pWebview  
     * @param array  
     *  
     *    taskId    temp[0]  
     *    AllLen    temp[1]  
     *    nowCount  temp[2]  
     */  
    public void sendTempFile(IWebview pWebview, JSONArray array){  
        String CallBackID = array.optString(0);  
        String cutPath = array.optString(1);  
        String URLPath = array.optString(2);  

        byte[] buffer = new byte[readStep];  
        File file = new File(cutPath);  
        File[] fs = file.listFiles();  
        for (File f : fs){  
            String newString = f.getName().toString().replace(".part","");  

            Pattern pen = Pattern.compile("_");  

            String[] temp = pen.split(newString);  

            String fileName = temp[3];  
            Log.e("fileName",temp[3]);  
            //获取文件大小  
            FileInputStream fst = null;  
            try {  
                fst = new FileInputStream(f.getPath());  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            }  
            try {  
                fileSize = fst.available();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            //执行异步上传提交  
            asyncSendTempFiles(URLPath+"&task_id="+temp[0]+"&fileSize="+fileSize,f.getPath(),fileName,buffer,0,Integer.parseInt(temp[1]),Integer.parseInt(temp[2]),pWebview,CallBackID);  
        }  
    }  

    public void asyncSendTempFiles(final String urlPath, final String filePath, final String fileName, final byte[] buffer, final int count, final int allLength, final int nowCount, final IWebview pWebview, final String CallBackID){  

        AsyncTask<String, Void, String> execute = new AsyncTask<String, Void, String>() {  
            public void execute(String urlPath, String filePath, String fileName, byte[] buffer, int count, int allLength, int nowCount) {  
            }  

            @Override  
            protected String doInBackground(String... params) {  
                java.net.HttpURLConnection connection = null;  

                try {  
                    Log.e("urlPath",urlPath+"&allLength="+allLength+"&nowCount="+nowCount+"&fileName="+URLEncoder.encode(fileName, "UTF-8"));  
                    URL url = new URL(urlPath+"&allLength="+allLength+"&nowCount="+nowCount+"&fileName="+URLEncoder.encode(fileName, "UTF-8"));  
                    connection = (java.net.HttpURLConnection) url.openConnection();  
                    connection.setRequestMethod("POST");  
                    connection.setUseCaches(false);  
                    connection.setDoOutput(true);  

                    FileInputStream is = new FileInputStream(filePath);  
                    byte[] b = new byte[is.available()];  
                    Log.e("available",is.available()+"");  
                    is.read(b);  
                    OutputStream os = connection.getOutputStream();  
                    os.write(b);  
                    os.flush();  
                    os.close();  
                    if(connection.getResponseCode() == 200){  
                        Log.e("ResponseMessage",connection.getResponseMessage());  
                        return changeInputStream(connection.getInputStream(),"UTF-8");  
                    }else{  
                    }  
                } catch (IOException e) {  
                    Log.e("urlPath","url error");  
                    e.printStackTrace();  
                }  
                return "";  
            }  

            protected void onPostExecute(String result) {  
                Log.e("result",result);  
                try {  
                    JSONObject jsonObject = new JSONObject(result);  
                    //int resultCode = jsonObject.getInt("resultcode");  
                    String data = jsonObject.getString("status");  
                    Log.e("result-data",data);  
                    if(data == "0"){  
                        //传输成功 删除当前文件  
                        File file=new File(filePath);  
                        //文件是否存在  
                        if(file.exists())  
                        {  
                            file.delete();  
                            Log.e("result-data","文件已经被删除了");  
                        }  
                    }  

                } catch (JSONException e) {  
                    Log.e("result",result);  
                    e.printStackTrace();  
                }  
//                JSONArray newArray = new JSONArray();  
//                newArray.put(result);  
//                JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, true);  

            }  

        }.execute();  
    }  

    /**  
     * 将一个输入流转换成指定编码的字符串  
     *  
     * @param inputStream  
     * @param encode  
     * @return  
     */  
    private static String changeInputStream(InputStream inputStream,  
                                            String encode) {  

        // 内存流  
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
        byte[] data = new byte[1024];  
        int len = 0;  
        String result = null;  
        if (inputStream != null) {  
            try {  
                while ((len = inputStream.read(data)) != -1) {  
                    byteArrayOutputStream.write(data, 0, len);  
                }  
                result = new String(byteArrayOutputStream.toByteArray(), encode);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
        return result;  
    }  
继续阅读 »

最近公司项目需求做大文件的单点续传

分享下

java类代码

后台异步切割文件 切完返回true

/**  
     * 切割文件保存到指定目录 根据指定名称保存   
     * @param pWebview  
     * @param array  
     */  
    public void cutFile(final IWebview pWebview, JSONArray array){  
        final String CallBackID = array.optString(0);  
        final String filePath = array.optString(2);  
        final String cutPath = array.optString(3);  

        AsyncTask<String, Void, String> execute = new AsyncTask<String, Void, String>() {  
            public void execute(String taskId, String filePath, String cutPath) {  
            }  

            @Override  
            protected String doInBackground(String... params) {  
                java.net.HttpURLConnection connection = null;  

                byte[] buffer = new byte[readStep];  
                FileInputStream file = null;  
                File f =new File(filePath);  
                String fileName=f.getName();  
                try {  
                    file = new FileInputStream(filePath);  
                    int len = 0;  
                    int AllLen = 0;  
                    try {  
                        FileInputStream fs = new FileInputStream(filePath);  
                        fileSize = fs.available();  
                        AllLen = fileSize / (readStep);  
                        if(fileSize % (readStep) > 0){  
                            AllLen++;  
                        }  
                    } catch (IOException e) {  
                        // TODO Auto-generated catch block  
                        e.printStackTrace();  
                    }  
                    int nowCount = 1;  
                    while ((len = file.read(buffer)) > 0) {  
                        String strFilePath = cutPath+fileName+".part";  
                        try {  
                            File cutfile = new File(strFilePath);  
                            if (!cutfile.exists()) {  
                                Log.e("TestFile", "Create the file:" + strFilePath);  
                                cutfile.getParentFile().mkdirs();  
                                cutfile.createNewFile();  
                            }  
                            RandomAccessFile raf = new RandomAccessFile(cutfile, "rwd");  
                            raf.seek(0);  
                            raf.write(buffer,0,(int)len);  
                            raf.close();  
                        } catch (Exception e) {  
                            Log.e("TestFile", "Error on write File:" + e);  
                        }  
                        nowCount++;  
                    };  
                } catch (FileNotFoundException e) {  
                    e.printStackTrace();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  

                return "abc";  
            }  

            protected void onPostExecute(String result) {  
                Log.e("result",result);  
                if(result == "abc"){  
                    JSONArray newArray = new JSONArray();  
                    newArray.put(true);  
                    JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, true);  
                }  

            }  

        }.execute();  

    }

后台异步提交文件夹中所有文件碎片

/**  
     *  
     * @param pWebview  
     * @param array  
     *  
     *    taskId    temp[0]  
     *    AllLen    temp[1]  
     *    nowCount  temp[2]  
     */  
    public void sendTempFile(IWebview pWebview, JSONArray array){  
        String CallBackID = array.optString(0);  
        String cutPath = array.optString(1);  
        String URLPath = array.optString(2);  

        byte[] buffer = new byte[readStep];  
        File file = new File(cutPath);  
        File[] fs = file.listFiles();  
        for (File f : fs){  
            String newString = f.getName().toString().replace(".part","");  

            Pattern pen = Pattern.compile("_");  

            String[] temp = pen.split(newString);  

            String fileName = temp[3];  
            Log.e("fileName",temp[3]);  
            //获取文件大小  
            FileInputStream fst = null;  
            try {  
                fst = new FileInputStream(f.getPath());  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            }  
            try {  
                fileSize = fst.available();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            //执行异步上传提交  
            asyncSendTempFiles(URLPath+"&task_id="+temp[0]+"&fileSize="+fileSize,f.getPath(),fileName,buffer,0,Integer.parseInt(temp[1]),Integer.parseInt(temp[2]),pWebview,CallBackID);  
        }  
    }  

    public void asyncSendTempFiles(final String urlPath, final String filePath, final String fileName, final byte[] buffer, final int count, final int allLength, final int nowCount, final IWebview pWebview, final String CallBackID){  

        AsyncTask<String, Void, String> execute = new AsyncTask<String, Void, String>() {  
            public void execute(String urlPath, String filePath, String fileName, byte[] buffer, int count, int allLength, int nowCount) {  
            }  

            @Override  
            protected String doInBackground(String... params) {  
                java.net.HttpURLConnection connection = null;  

                try {  
                    Log.e("urlPath",urlPath+"&allLength="+allLength+"&nowCount="+nowCount+"&fileName="+URLEncoder.encode(fileName, "UTF-8"));  
                    URL url = new URL(urlPath+"&allLength="+allLength+"&nowCount="+nowCount+"&fileName="+URLEncoder.encode(fileName, "UTF-8"));  
                    connection = (java.net.HttpURLConnection) url.openConnection();  
                    connection.setRequestMethod("POST");  
                    connection.setUseCaches(false);  
                    connection.setDoOutput(true);  

                    FileInputStream is = new FileInputStream(filePath);  
                    byte[] b = new byte[is.available()];  
                    Log.e("available",is.available()+"");  
                    is.read(b);  
                    OutputStream os = connection.getOutputStream();  
                    os.write(b);  
                    os.flush();  
                    os.close();  
                    if(connection.getResponseCode() == 200){  
                        Log.e("ResponseMessage",connection.getResponseMessage());  
                        return changeInputStream(connection.getInputStream(),"UTF-8");  
                    }else{  
                    }  
                } catch (IOException e) {  
                    Log.e("urlPath","url error");  
                    e.printStackTrace();  
                }  
                return "";  
            }  

            protected void onPostExecute(String result) {  
                Log.e("result",result);  
                try {  
                    JSONObject jsonObject = new JSONObject(result);  
                    //int resultCode = jsonObject.getInt("resultcode");  
                    String data = jsonObject.getString("status");  
                    Log.e("result-data",data);  
                    if(data == "0"){  
                        //传输成功 删除当前文件  
                        File file=new File(filePath);  
                        //文件是否存在  
                        if(file.exists())  
                        {  
                            file.delete();  
                            Log.e("result-data","文件已经被删除了");  
                        }  
                    }  

                } catch (JSONException e) {  
                    Log.e("result",result);  
                    e.printStackTrace();  
                }  
//                JSONArray newArray = new JSONArray();  
//                newArray.put(result);  
//                JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, true);  

            }  

        }.execute();  
    }  

    /**  
     * 将一个输入流转换成指定编码的字符串  
     *  
     * @param inputStream  
     * @param encode  
     * @return  
     */  
    private static String changeInputStream(InputStream inputStream,  
                                            String encode) {  

        // 内存流  
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
        byte[] data = new byte[1024];  
        int len = 0;  
        String result = null;  
        if (inputStream != null) {  
            try {  
                while ((len = inputStream.read(data)) != -1) {  
                    byteArrayOutputStream.write(data, 0, len);  
                }  
                result = new String(byteArrayOutputStream.toByteArray(), encode);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
        return result;  
    }  
收起阅读 »

初学一个多月,终于制作完成了一个简陋的app并上架了!

上架 App

首先,感谢社区里的大神们和QQ群里的大神们的帮助,自己摸爬滚打制作的简易APP终于上线了。

苹果的app store也顺利上线!

感觉自己又有信心了!

首先,感谢社区里的大神们和QQ群里的大神们的帮助,自己摸爬滚打制作的简易APP终于上线了。

苹果的app store也顺利上线!

感觉自己又有信心了!