2.html通过ajax上传base64的图片,服务端通过Servlet接收数据并在本地创建文件

一、应用场景

本地上传一张图片,回显在img中

然后点击按钮通过ajax上传到服务器,服务器拿到图片在本地保存

二、前端

1.点击按钮本地上传图片,回显在img

首先打开本地文件的需求需要file类型的input,这个input一般不显示出来,用来读取本地文件。那就把这个input设置成隐藏,另外设置一个按钮,点击这个按钮触发上面这个input的onclick()事件。选择好文件之后,input中就有file文件了,这时候通过这是input的onchange()函数(状态改变),进行图片回显。

2.file类型的input,设置成隐藏,状态改变,触发showImg()函数,传入自身

<input type="file" id="btn_file" style="display:none" onchange="showImg(this)">

3.点击按钮,触发F_Open_dialog()函数

<button type="button" class="btn btn-primary" style="font-size:20px" onclick="F_Open_dialog()">点击本地上传</button>

4.F_Open_dialog()函数触发上方input的点击事件,进行本地文件上传操作

<script type="text/javascript">

    function F_Open_dialog(){

        document.getElementById("btn_file").click();

    }

</script>

5.数据上传完成保存在input中,这时候input状态改变,触发showImg()函数

function showImg(input){

    var file=input.files[0];

    var url=window.URL.createObjectURL(file);

    console.log(url)

    document.getElementById('myimage').src=url;

     }

这里这个files[0]注意是复数,如果input属性multiple="multiple",那么可以同时选中多个文件上传到input中,如果只是一个文件,就是第一个文件,下标是0。

通过URL,创造一个临时的blob资源地址,把这个地址赋给image标签做到照片的回显

blob(Binary Large Object)二进制大对象,file类型的文件是blob的子类。

算是临时给一个文件一个url,这个url只用来回显,传送这个blob地址到后端没用。

6.点击图片上传按钮,触发F_Submit()函数

<button type="button" class="btn btn-primary" style="font-size:20px" onclick="F_Submit()">点击开始识别</button>

7.F_Submit()函数

function F_Submit(){

    var file=$("#gou").find("input")[0].files[0];

    var reader=new FileReader();

    reader.readAsDataURL(file);

    var data_64;

        reader.onloadend=function(e){

        data_64=e.target.result;

        console.log(data_64)

        var url="myservlet?method=processPicture";

        console.log(url)

        $.ajax({

        url:url,

        type:'POST',

        data:data_64,

        // data:formData

         contentType:false,

        processData:false,//这个很有必要,不然不行

        //dataType:"json",

        success:function(data){                                        document.getElementById('result').innerText = data;

        }

        }); 

     };

    }

找到file类型的图片,通过FileReader的readAsDataURL方法,把file转换成base64类型的数据。这个FileReader读取有一段时间,如果ajax写在外面,这个数据可能还没读完,所以我把ajax写在了FileReader读完的函数内,读完把这个数据塞在data中,url写上你请求的内容。这个data中的数据会放入http报文的body部分。之前想过把base64字符串放在url中,结果报错,显示报文头太长。

2.html通过ajax上传base64的图片,服务端通过Servlet接收数据并在本地创建文件

还有,传图片一般用post,不限制大小,get方式会限制大小

下面有个success方法,如果ajax请求成功,则执行方法中的内容。

 

三、服务端(servlet)

1.服务端通过request的getReader()方法得到前端传来的httpbody部分,即ajax的data属性值

BufferedReader reader = req.getReader();

String msg=null;

String line;

while((line=reader.readLine())!=null)

    msg+=line;

2.把获取到的base64字符串进行切割操作

String myString=msg.substring(msg.lastIndexOf(',')+1);

本身base64格式如下,从逗号开始切就行,拿后面的主体部分

2.html通过ajax上传base64的图片,服务端通过Servlet接收数据并在本地创建文件

3.base64字符串转file

public File base64ToFile(String base64str){

    System.out.println("base64 to file ....");

    if(base64str==null||"".equals(base64str)){

        return null;

        }

    byte[] buff=Base64.decode(base64str);

    File file=null;

    FileOutputStream fout=null;

    try {

        file=File.createTempFile("tmp", ".jpg");

        fout=new FileOutputStream(file);

        fout.write(buff);

        } catch (Exception e) {

        }

    if(fout!=null){

    try {

        fout.close();

        } catch (Exception e) {

           }

    }

 return file;

 }

4.本地保存文件(脚本)

public void saveImage(File file){

    System.out.println("saveImage..");

    String strPath="D:/myImg/1.jpg";

    File myfile=new File(strPath);

    try {

        if(myfile.exists()) //目录下有文件就删除

            myfile.delete();

        if(!myfile.getParentFile().exists())   //文件夹不存在创建文件夹

             myfile.getParentFile().mkdirs();

              FileInputStream fin=new FileInputStream(file);

              FileOutputStream fout=new FileOutputStream(myfile);

              byte[] myByteArray=new byte[(int) file.length()];

              int n=0;

              while((n=fin.read(myByteArray))!=-1)

                   fout.write(myByteArray, 0, n);

              fout.close();

              fin.close();

          }

          catch (Exception e) {

              // TODO: handle exception

          }    

     }

5.最后就是通过上面两个封装好的脚本,把base64数据转换成,file,再保存在本地

 

6.如果需要给html返回数据,找response对象,找到它的写入器,把内容写入就行,ajax的success函数能收到这个数据

PrintWriter writer=resp.getWriter();
        writer.write(myString);

四.小结

1.客户端给服务端传送图片,还能通过formdata的形式,在formdata中直接塞入file类型的数据,通过ajax传送

2.http报文如下

方U协 行头体

这个url在请求行中,不能过长,所以不能放base64的图片

通过ajax传送的data中的数据会放在报头体内

报文头中是一些属性和属性值(键值对)

2.html通过ajax上传base64的图片,服务端通过Servlet接收数据并在本地创建文件

3.url

2.html通过ajax上传base64的图片,服务端通过Servlet接收数据并在本地创建文件

URI(Uniform Resourse Identifier)统一资源标识符

URL(Uniform Resourse Locator)统一资源定位符

一个统一资源定位器(URL) 用于定位万维网上的文档

URN(Uniform Resourse Name)统一资源名称

后续可以再研究研究这个url,有点神奇