尝试用kotlin做一个app

Posted vocus

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尝试用kotlin做一个app相关的知识,希望对你有一定的参考价值。

JSP后台管理系统

开发工具是IntelliJ IDEA+tomcat+mysql5.6.19+mysql-connector-java-5.1.48.jar+easyui+kindeditor

之前也有记录一些Servlet基础(java,idea)

这篇我只把一些重要的记录一下

easyui官方文档

kindeditor官方文档

easyui很简单,而且中文文档介绍得很详细,对照文档做就好了

kindeditor问题比较多,这里记录一下

准备工作

mysql数据库test中建立t_hp_new表

create table t_hp_new(id int primary key auto_increment,title varchar(100),author varchar(30),pubdate datetime,origin varchar(50),href varchar(200),thumb mediumtext,content mediumtext);

 

 thumb是缩略图,为blob类型,这里先不考虑这个。建立New类been数据的时候,把thumb定义为String类型

kindeditor的使用

·初始化

在需要使用kindeditor的地方添加

    <link type="text/css" href="kindeditor-4.1.11-zh-CN/kindeditor/themes/default/default.css" rel="stylesheet">
    <script type="text/javascript" src="kindeditor-4.1.11-zh-CN/kindeditor/kindeditor-all.js"></script>
    <script type="text/javascript" src="kindeditor-4.1.11-zh-CN/kindeditor/kindeditor-all-min.js"></script>
    <script type="text/javascript" src="kindeditor-4.1.11-zh-CN/kindeditor/lang/zh-CN.js"></script>

内容编辑区域是一个富文本框

<th> <textarea id="editor" name="editor" style="height:480px;width:900px"></textarea> </th>

初始化

    <script type="text/javascript">
        let editor
        KindEditor.ready(function (K) {
            editor=K.create(\'textarea[id="editor"]\',{
                items:[\'source\', \'undo\', \'|\', \'redo\', \'|\', \'cut\', \'copy\', \'paste\', \'|\', \'plainpaste\', \'|\', \'fontname\', \'fontsize\', \'forecolor\', \'hilitecolor\', \'bold\', \'italic\', \'underline\', \'strikethrough\', \'|\', \'justifyleft\', \'justifyright\', \'justifycenter\', \'|\', \'image\', \'insertfile\', \'link\', \'code\'],
            })
        })
    </script>

items:可选

添加插入图片功能

添加uploadJson:"kindeditor-4.1.11-zh-CN/kindeditor/jsp/upload_json.jsp"

把jsp/lib下的jar包粘贴到web工程的lib目录下

此时提示上传目录不存在

然后修改upload_json.jsp的savepath

String savePath=request.getSession().getServletContext().getRealPath("/");

在这里顺便把saveUrl也改了,因为后面会用到saveUrl

(这个问题不一定是这样,也可以试着在web目录下新建一个attached目录)

把上图图片插入到编辑框里

 

 

 默认上传图片后,点显示html源码它是这样的,浏览器错误提示Not allowed to load local resource

<img>标签不允许引用本地磁盘的图片

一种解决办法是把src后的url的图片转换成base64编码

定义编码函数

看情况导入包,如果提示错误The import java.util.Base64.Encoder collides with another import statement就去掉

 

<%@ page import="java.util.Base64.Encoder" %>
<%@ page import="java.util.Base64.Decoder" %>

 

 

 

//图片编码
<%!
    public String getBaseImg(String imgPath){
        InputStream in=null;
        byte[] data=null;

        try{
            in=new FileInputStream(imgPath);
            data=new byte[in.available()];
            in.read(data);
            in.close();

        }catch (Exception e) {
            e.printStackTrace();
        }
        Base64.Encoder encoder=Base64.getEncoder();
        String encode=encoder.encodeToString(data);
        return encode;
    }

%>

在传递saveUrl之前,对saveUrl进行编码处理

JSONObject obj = new JSONObject();
//
String saveUrlEncode="data:image/jpeg;base64,"+getBaseImg(saveUrl + newFileName);
obj.put("error", 0);
obj.put("url", saveUrlEncode);
out.println(obj.toJSONString());

记得要加"data:image/jpeg;base64,"这个加在base64编码前,<img>标签才能正常显示

kindeditor编辑框内容上传

在表单提交之前首先要把kindeditor的内容同步到textarea中,使用

editor.sync()

那这样提交一下就厉害了,发送这么一长串请求会遇到问题:

比如java.lang.IllegalArgumentException: Request header is too large 请求头太大

具体可以参考Servlet基础(java,idea)之前提到改成post会乱码,是因为没有添加req.setCharacterEncoding("utf-8");(那这里就可以把get请求改成post了,不用之后的对内容进行url编码)

还有一个easyui也不能正常读取新闻列表了

这是因为之前读取数据库的数据,把数据转换成Json数据(使用json-lib),而json数据里不能存在html的一些标签,特殊符号的。具体的错误提示at net.sf.json.util.JSONTokener.syntaxError

那在New的java been类中,添加一个自定义的tostring1()函数,把content转化为url编码

 

public String toString1() {
        Long date=0L;
        if(pubdate!=null){
            date=pubdate.getTime();
        }
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        String dateString=sdf.format(date);

        String contentUrlEncode= URLEncoder.encode(content);

        return "{" +
                "id=" + id +
                ", title=\'" + title + \'\\\'\' +
                ", author=\'" + author + \'\\\'\' +
                ", pubDate=" + dateString +
                ", origin=\'" + origin + \'\\\'\' +
                ", href=\'" + href + \'\\\'\' +
                ", content=\'" + contentUrlEncode + \'\\\'\' +
                ", thumb=\'" + thumb + \'\\\'\' +
                \'}\';
    }

在执行select * from t_hp_new查询的时候,会输出很长的字段值,那这个暂时没办法了

关于缩略图上传(也可以是通用图片上传)

先是form表单要改一下,添加enctype="multipart/form-data"

<form id="fm" method="post" enctype="multipart/form-data">

<input type="file" id="thumb" name="thumb"/>

点击提交,发现浏览器上传这样一段数据(request payload)

------WebKitFormBoundary8BC9g9ZlOORkXrkN
Content-Disposition: form-data; name="title"

a
------WebKitFormBoundary8BC9g9ZlOORkXrkN
Content-Disposition: form-data; name="thumb"; filename="1.png"
Content-Type: image/png


------WebKitFormBoundary8BC9g9ZlOORkXrkN
Content-Disposition: form-data; name="editor"

b
------WebKitFormBoundary8BC9g9ZlOORkXrkN
Content-Disposition: form-data; name="author"

c
------WebKitFormBoundary8BC9g9ZlOORkXrkN
Content-Disposition: form-data; name="origin"

d
------WebKitFormBoundary8BC9g9ZlOORkXrkN
Content-Disposition: form-data; name="href"

e
------WebKitFormBoundary8BC9g9ZlOORkXrkN--

(改成get请求,好像是正常title=%E5%93%88%E5%93%88&thumb=1.jpg&editor=00&author=ee&origin=dd&href=ex;这里还是改回post)

上面那段字符串,分为两种域,一种是图片文件的域

------WebKitFormBoundary8BC9g9ZlOORkXrkN
Content-Disposition: form-data; name="thumb"; filename="1.png"
Content-Type: image/png

一种是普通form的域

d
------WebKitFormBoundary8BC9g9ZlOORkXrkN
Content-Disposition: form-data; name="href"

备注:

MIME媒体类型,是描述报文实体主体内容的一些保准化名称(如,text/html,image/jpeg)

request.getContentType函数

java.lang.String getContentType()
Returns the MIME type of the body of the request, or null if the type is not known. For HTTP servlets, same as the value of the CGI variable CONTENT_TYPE.
Returns:
a String containing the name of the MIME type of the request, or null if the type is not known

这里返回的是multipart/form-data; boundary=----WebKitFormBoundarye0S1O6ob5tGT8sqx

 

接下来就有点傻了,我们要在字符串里,截取文件filename,Content-Type和name以及下面的值。那就先随便试一下

这个看起来很复杂,但是思路是挺简单的。这里没必要看别人的代码,自己动手实践一下就好

public class main {
    public static void main(String[] args) {
        String str = "------WebKitFormBoundaryoAZzkCVEWZ0J434f\\n" +
                "Content-Disposition: form-data; name=\\"title\\"\\n" +
                "WO\\n" +
                "------WebKitFormBoundaryoAZzkCVEWZ0J434f\\n" +
                "Content-Disposition: form-data; name=\\"thumb\\"; filename=\\"1.jpg\\"\\n" +
                "Content-Type: image/png\\n" +
                "------WebKitFormBoundaryoAZzkCVEWZ0J434f\\n" +
                "Content-Disposition: form-data; name=\\"editor\\"\\n" +
                "HAHA\\n" +
                "------WebKitFormBoundaryoAZzkCVEWZ0J434f\\n" +
                "Content-Disposition: form-data; name=\\"author\\"\\n" +
                "DD\\n" +
                "------WebKitFormBoundaryoAZzkCVEWZ0J434f\\n" +
                "Content-Disposition: form-data; name=\\"origin\\"\\n" +
                "EE\\n" +
                "------WebKitFormBoundaryoAZzkCVEWZ0J434f\\n" +
                "Content-Disposition: form-data; name=\\"href\\"\\n" +
                "SS\\n" +
                "------WebKitFormBoundaryoAZzkCVEWZ0J434f--\\n";
        String contentType = "multipart/form-data; boundary=----WebKitFormBoundaryoAZzkCVEWZ0J434f";
        int position = contentType.indexOf("boundary=");

        position += ("boundary=").length();
        String boundary = "--" + contentType.substring(position);

        String lastboundary = boundary + "--";
        System.out.println(lastboundary);

        BufferedReader reader = new BufferedReader(new StringReader(str));
        String s = null;
        while (true) {
            try {
                //读取每一行,当读取到最末一行或者返回null的时候结束
                s = reader.readLine();
                if (s == lastboundary || s == null) break;
                if (s.startsWith(boundary)) {
                    s = reader.readLine();//读取下一行
                    if (s != null) {
                       if(s.indexOf("filename=")!=-1){
                           //上传图片域
                           //截取文件名
                           int pos=s.indexOf("filename=");
                           pos+="filename=".length();
                           String filename=s.substring(pos);
                           filename=filename.replace("\\"","");
                           //继续获取图片文件类型
                           s=reader.readLine();
                           pos=s.indexOf("Content-Type:");
                           pos+="Content-Type:".length();
                           String type=s.substring(pos).replace(" ","");
                           System.out.println(type);
                           //判断图片类型应该是image/jpeg,image/png,image/gif
                           if(type.equals("image/jpeg")||type.equals("image/png")||type.equals("image/gif")){
                               System.out.println("上传图片格式正确");
                           }else {
                               System.out.println("只支持上传jpg,png,gif文件");
                           }

                       }else {
                           //普通from域
                           int pos=s.indexOf("name=");
                           pos+="name=".length();
                           String name=s.substring(pos);
                           name=name.replace("\\"",""); //获得name
                           //再读取下一行获取到值
                           s=reader.readLine();
                           String value=s;
//                           System.out.println("{name:"+name+",value:"+value+"}");

                       }
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}
View Code

那之后的重点是获得图片流数据。当执行

       ServletInputStream in = req.getInputStream();
        int len = req.getContentLength(); //获得请求数据字节长度
        byte[] orginData = new byte[len];//len字节数组
        orginData=in.readAllBytes();
        in.close();
        String orginStr=new String(orginData);
        System.out.println(orginStr);

会输出一段乱码,那么乱码的位置就是图片流数据的位置。先找到字符串orginStr乱码的开始,结束位置,过程大概是这样

这个过程的代码如下

public class AddNewsServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//    req.setCharacterEncoding("utf-8");
//    String title=req.getParameter("title");
//    String author=req.getParameter("author");
//    String content=req.getParameter("editor");
//    String origin=req.getParameter("origin");
//    String href=req.getParameter("href");

        //获得请求流数据,并转换成字符串
        ServletInputStream in = req.getInputStream();
        int len = req.getContentLength(); //获得请求数据字节长度
        byte[] orginData = new byte[len];//len字节数组
        orginData=in.readAllBytes();
        in.close();
        String orginStr=new String(orginData);

        String contentType=req.getContentType();//
        int position = contentType.indexOf("boundary=");

        position += ("boundary=").length();
        String boundary = "--" + contentType.substring(position);
        String lastboundary = boundary + "--";

        BufferedReader reader = new BufferedReader(new StringReader(orginStr));

        String savePath=req.getSession().getServletContext().getRealPath("/")+"thumb/";
        String s = null;
        JSONObject params=new JSONObject();
        while (true) {
            try {
                //读取每一行,当读取到最末一行或者返回null的时候结束
                s = reader.readLine();
                if (s == lastboundary || s == null) break;
                if (s.startsWith(boundary)) {
                    s = reader.readLine();//读取下一行
                    if (s != null) {
                        if(s.indexOf("filename=")!=-1){
                            //上传图片域
                            //截取文件名
                            int pos=s.indexOf("filename=");
                            pos+="filename=".length();
                            String filename=s.substring(pos);
                            filename=filename.replace("\\"","");
                            //继续获取图片文件类型
                            s=reader.readLine();
                            pos=s.indexOf("Content-Type:");
                            pos+="Content-Type:".length();
                            String type=s.substring(pos).replace(" ","");
                            System.out.println(type);
                            //判断图片类型应该是image/jpeg,image/png,image/gif
                            if(type.equals("image/jpeg")||type.equals("image/png")||type.equals("image/gif")){
                                System.out.println("上传图片格式正确");
                                //重命名图片名称
                                filename=filename.substring(filename.lastIndexOf("."));
                                SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
                                String ymd=sdf.format(new Date());
                                String newFilename=ymd+filename;

                                //获得图片流开始位置
                                int typeStart=orginStr.indexOf("Content-Type"); //定位到Content-Type开始位置
                                int fileStart=orginStr.indexOf("\\n",typeStart)+1;//定位到Content-Type下一行
                                fileStart=orginStr.indexOf("\\n",fileStart)+1;//再下一行
                                //获得图片流结束的位置
                                int fileEnd=orginStr.indexOf(boundary,fileStart);//从文件开始处开始查找,直到第一个boundary出现
                                String saveFile=orginStr.substring(fileStart,fileEnd);
//                                System.out.println(saveFile);
//                                System.out.println(orginStr);
                                int contentStart=orginStr.substring(0,fileStart).getBytes().length;
                                int contentEnd=orginStr.substring(0,fileEnd).getBytes().length;

                                FileOutputStream out=new FileOutputStream(savePath+newFilename);
                                out.write(orginData,contentStart,contentEnd);
                                out.close();

                            }else {
                                System.out.println("只支持上传jpg,png,gif文件");
                            }

                        }else {
                            //普通form域
                            int pos=s.indexOf("name=");
                            pos+="name=".length();
                            String name=s.substring(pos);
                            name=name.replace("\\"",""); //获得name
                            //再读取下一行获取到值,可能是空行,那就继续读下一行
                            while ((s=reader.readLine()).equals("")){ }
                            String value=s;
                            //添加进json
                            params.put(name,value);

                        }
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        System.out.println(params);

        //获得系统的时间
//    Timestamp pubdate=new Timestamp(System.currentTimeMillis());
//    int count=new T_NewImpl().addNewsForHp(title,author,content,origin,href,pubdate);
//    resp.setContentType("text/html;charset=utf-8");
//    JSONObject result=new JSONObject();
//    result.put("count",count);
//
//    resp.getWriter().println(result);
//    resp.getWriter().flush();
//    resp.getWriter().close();


    }
}

 

那如果是这样,看来数据库的thumb字段还是让它是varchar类型好了,就保存一个图片的地址;或者要保存到数据库的话,就把图片流数据写到数据库里吧,之前尝试过,在这里面常用sql语句(mysql测试)

简直不要太累

源码

链接:https://pan.baidu.com/s/1Qu-OYX_ppqEBYmWvRk11aw
提取码:u1ht

 

补充:

·中文乱码解决

String orginStr = new String(orginData,"utf-8");

但是这样强制编码,图片就会出错!!!!!!!!!!!!

所以要设置getBytes("utf-8")。这样弄了之后如果是图片上传不完整,那就在判断读取的行s是普通form域之后,把s转成utf-8吧

·editor里面的内容也是多行,所以要加个判断

 

if(name.equals("editor")){
                                for(;;) {
                                    value += s;
                                    reader.mark(1);
                                    s=reader.readLine();
                                    if(s.equals(boundary)) {
                                        reader.reset();
                                        break;
                                    }
                                }
                            }else value = s;

 

·

 

以上是关于尝试用kotlin做一个app的主要内容,如果未能解决你的问题,请参考以下文章

尝试用kotlin做一个app

尝试用kotlin做一个app

尝试用kotlin做一个app(十六)

尝试用kotlin做一个app

如何在 Kotlin 片段内的按钮之间切换片段?

如何在kotlin的片段内显示网格视图?