java存储H5上传的图片

来源:互联网 发布:c语言比较字符串长度 编辑:程序博客网 时间:2024/06/09 21:25

最近的业务需要配合前端提供一个上传图片的接口,前端是一个Html5的页面,使用的上传方式和原有上传方式不太一样,因此特别记录一下。

第一种,页面使用表单提交,后台使用commons-fileupload.jar来接收。

其实这种方法就是传统的表单提交方式,前端页面如下:

<form id="form" action="http://localhost:8080/emission/SaveImage" method="post" enctype="multipart/form-data">    <input class="m_camera" type="file" accept="image/*" name="file_img" capture="camera" id="cameraInput" >    <input type="hidden" value="123455788" name="orderid" />    <input type="hidden" value="" name="hidden" id="j_thumb" />    <!--  input type="submit" value="submit" name="sbt" id="sbt" --></form>

JS中获得图片压缩一下,然后放到表单中传过来,其实这个东西本来是个很简单的业务,但由于其中的两行JS代码的误会,导致这个东西搞了很久,这两行代码时这样的

var r = i.toDataURL("image/jpeg", .8);document.getElementById("j_thumb").value = r.substr(22)

看起来是给”j_thumb“这个input赋值,然后提交到页面,实际上并不是这样的。当我在后台使用commons-fileupload插件解析request时,在 ”j_thumb“这个对象中,并没有看到对应的文件,直到最后把整个request输出出来,才发现原来这个东西是在file_img这个对象中传过来的,可能是因为浏览器自动处理吧,把图片放到了这个type为file的标签中。得到这个对象后就简单很多了。直接读取一下解析后的文件流,这里没有尝试判断是否文本域的方法,如何使用判断文本域的方法来处理图片,请参见前文:微软云+Servlet实现图片上传接口 所需jar包commons-fileupload也可以在前文中找到。

以下是后台接收图片的代码:

        Data.writeLog(Global.errPath1, "访问到SaveImage+test\r\n");        DiskFileItemFactory factory = new DiskFileItemFactory();        factory.setSizeThreshold(8192);        factory.setRepository(tempPath);        ServletFileUpload upload = new ServletFileUpload(factory);        upload.setSizeMax(1000000 * 20);        String orderid = "";        String suffix = "";        try {            /* 解析request 取得表单域迭代器 */            FileItemIterator fii = upload.getItemIterator(request);            /* 遍历迭代器 ,这里也可以使用while循环*/            for (final FileItemIterator itemIterator = fii; itemIterator.hasNext();) {                final FileItemStream item = itemIterator.next();                /*直接根据对象name进行筛选*/                if ("orderid".equals(item.getFieldName())) {                    /*读取request的输入流*/                    BufferedReader responseReader = new BufferedReader(                            new InputStreamReader(item.openStream(), "UTF-8"));                    String readLine;                    StringBuffer responseSb = new StringBuffer();                    while ((readLine = responseReader.readLine()) != null) {                        responseSb.append(readLine);                    }                    /*获得表单文字域*/                    orderid = responseSb.toString();                }                if ("file_img".equals(item.getFieldName())) {                    /*截取name获得文件后缀名*/                    String fileName = item.getName();                    int index = fileName.indexOf(".");                    suffix = fileName.substring(index, fileName.length());                    /*从request流中获得输入流*/                    BufferedInputStream inputStream = new BufferedInputStream(item.openStream());                    /*定义输出流*/                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();                    /*复制输入流到输出流*/                    Streams.copy(inputStream, outputStream, true);                    /*生成文件图片*/                    File picFile = new File(                            "D:\\feng\\perl-work\\zzq\\emission\\imageUpload\\" + directory + "\\" + saveName + suffix);                    if (picFile.getParentFile() != null && !picFile.getParentFile().exists()) {                        picFile.getParentFile().mkdirs();                    }                    if (!picFile.exists()) {                        picFile.createNewFile();                    }                    /*写入文件并关闭流*/                    OutputStream fileOutputStream = new FileOutputStream(picFile);                    outputStream.writeTo(fileOutputStream);                    inputStream.close();                    outputStream.close();                    fileOutputStream.close();                }            }        } catch (Exception e) {            message.put("code", "-1");            message.put("message", "接收文件失败" + e.getMessage());            message.put("id", request.getParameter("orderid"));            writer.println(new JSONObject(message).toString());            request.setAttribute("orderId", orderid);        }

这种范式的一个问题就是对app不太友好,因为表单提交就意味着url跳转,只能在服务器端的网页上使用这种上传图片的方法。

第二种,使用ajax异步调用图片存储接口
ajax也是现在很流行图片上传方法,即将图片处理成二进制文本,然后作为字符串传输给后台。前台代码如下:

function saveImage(txt) {    var id = "";    alert(txt)    $.ajax({        url: "http://localhost:8080/emission/SaveImage2",        type: "post",        data: {            orderId: 39,            file_img: txt        },        success: function(response) {            alert(response);            var dataobj = eval("(" + response + ")")        }    })}

txt即为处理过的二进制文本图片。

后端接收代码如下:

        String orderid = request.getParameter("orderId");        String image = request.getParameter("file_img");        /*进行base64解码*/        byte[] images = Base64.decodeBase64(image);        File picFile = new File(                "D:\\feng\\perl-work\\zzq\\emission\\imageUpload\\" + directory + "\\" + saveName + ".png");        if (picFile.getParentFile() != null && !picFile.getParentFile().exists()) {            picFile.getParentFile().mkdirs();        }        if (!picFile.exists()) {            picFile.createNewFile();        }        /*将bytes写入文件*/        FileOutputStream fos = new FileOutputStream(picFile);        fos.write(images);        fos.close();

由于前台有一个简单的压缩算法,使用了canvas对象的toDataURL方法,会将图片进行base64编码,因此后台接收的时候需要将对应的字符串进行解码。

小结:其实压缩图片上传是个很常见的业务,但是这其中的细节确实值得了解。最开始我们使用接口的形式,但是由于前后端不在一个服务器上,js调用的时候出现了跨域的问题。当我们使用jsonp传递参数试图解决这个问题的时候,由于图片压缩完是一个很长的字符串,因此可能超出了jsonp的限制,传输失败。这时候我们转用表单提交图片。由于对H5方法不熟悉,并且JS代码中压缩完的图片赋值给了一个hidden标签,对后台解析造成了很大的影响。事后推测,应该是浏览器对enctype=”multipart/form-data”形式的表单有自动的封装定义,即使将文件形式字符传给了hidden域,最终完成传递工作的还是type=“file”类型的input,而发现这个问题足足用了两天的时间,可以说是一个比较深刻的教训了。

0 0
原创粉丝点击