基于HTML5和JSP实现的图片Ajax上传和预览

本文对如何实现使用Ajax提交"multipart/form"格式的表单数据,已经如何在图片上传之前,在浏览器上进行预览。使用的主要相关技术HTML5的FILE API,XMLHttprequest Level2中对二进制文件上传的支持(通过构建FormData对象进行支持)以及Servlet 3.0支持的Multiconfig注解来支持文件的上传。在Servlet 3.0 规范之前通常使用第三方库如commons-fileupload进行解决文件上传。

  •  HTML5 中的 File 对象和FileReader对象

html5中标签<input type="file" id="imageFile" name="imageFile" multiple>可以设置multiple属性,可以选取多个文件,并且对HTML DOM模型提供支持,如var imageFile=document.getElementById("imageFile").files[0];document.getElementById("imageFile")返回的文件对象数组,这是由于支持multiple属性,因此我们即使没有设置这一属性,也得通过获取数组的第一个元素,才能获取该文件表示的File对象啊。在Jquery中可以var image=$("#imageFile").get(0).files[0];或者var image=$("#imageFile")[0].files[0]来获取对象。

这一File对象我们可以获取其中的文件名,MIME类型,大小等等信息。

通过FileReader对象,可以对File对象进行读取,显示等等。FileReader的读取操作为异步读取,因此我们得通过设置相关的事件处理程序,才能对读取的数据进行处理。

  • 事件处理程序
onabort  当读取操作被中止时调用.
onerror 当读取操作发生错误时调用.
onload  当读取操作成功完成时调用.
onloadend

 当读取操作完成时调用,不管是成功还是失败.

该处理程序在onload或者onerror之后调用.

onloadstart  当读取操作将要开始之前调用.
onprogress  在读取数据过程中周期性调用.

 

  • 方法概述
void abort() 中止该读取操作.在返回时,readyState属性的值为DONE.
void readAsArrayBuffer(in Blob blob)

开始读取指定的Blob对象或File对象中的内容.当读取操作完成时,readyState属性的值会成为DONE,

如果设置了onloadend事件处理程序,则调用.如果设置了onload事件处理程序,则在读取成功后调用.

同时,result属性中将包含一个ArrayBuffer对象以表示所读取文件的内容.

void readAsBinaryString(in Blob blob)

开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,

如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含所读取文件的原始二进制数据.

void readAsDataURL(in Blob blob)

开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,

如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.

void readAsText(in Blob blob, [optional] in DOMString encoding)

开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,

如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个字符串以表示所读取的文件内容.encoding 可选
一个字符串,表示了返回数据所使用的编码.如果不指定,默认为UTF-8.

 

  • 实现图片预览功能代码如下:由于需要在浏览器显示图像因此采用FileReader的 readAsDataURL接口。
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/jquery-1.12.0.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
<link href="css/bootstrap.css" rel="stylesheet">
<title>Insert title here</title>
<script>
    $(document).ready(function() {
        $("#imageFile").change(function() {
            var fileReader = new FileReader();
            fileReader.onload = function(e) {
                $("#previewImage").append("<span class='center-block text-success'>图像预览</span><image class='img-thumbnail' style='max-width:400px;height:auto;' src="+e.target.result+"/>");
            }
            var imageFile = this.files[0];
            fileReader.readAsDataURL(imageFile);
        });
        $("#send")
        .click(
                function() {
                        var xhr=new XMLHttpRequest();
                        xhr.open("post","fileUpload");
                        xhr.onreadystatechange = function() {
                            if (xhr.readyState == 4) {
                                if(xhr.status == 200){
                                alert("图片上传成功"); 
                            }else{
                                alert("图片上传失败")
                            }
                            }
                        };
                    var imageFile = $("#imageFile")[0].files[0];
                    var username=$("#username").val();
                    var myForm = new FormData();
                    myForm.append("username",username);
                    myForm.append("imageFile", imageFile);
                    xhr.send(myForm);
                });

    });
</script>
</head>
<body>
    <div class="container">
        <div class="panel">
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">图像上传和预览测试</h3>
                </div>
                <div class="panel-body">
                    <p id="previewImage"></p>
                    <form action="fileUpload" enctype="multipart/form-data"
                        method="post" class="form-inline">
                        <div class="form-group">
                            <label for="username">用户名</label>
                        </div>
                        <div class="form-group">
                            <input type="text" id="username" name="username" />
                        </div>
                        <div class="form-group">
                            <label for="imageFile">上传图片</label>
                        </div>
                        <div class="form-group">
                            <input type="file" id="imageFile" name="imageFile"
                                accept="image/jpeg" />
                        </div>

                        <button type="button" id="send" class="btn btn-primary">上传</button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

 

  • 实现Ajax图片上传,对于form数据的提交有成熟的jquery插件jquery.form.js可以实现ajax提交,并且对不支持FormData对象的浏览器进行支持。本文的实现方法仅对支持HTML5中的FormData浏览器使用。

服务端代码实现,在Servlet 3.0 规范中提供了@MultiConfig这一注解对需要处理"multipart/form"数据类型提交的Servlet进行支持,并且在通过HttServletRequest中的getParts()和getPart(String name)获取上传文件;Servlet 3.0之前则需要下载如commons-fileupload的第三方库进行支持,本文使用这一注解,Tomcat 7及以上版本对Servlet 3.0支持。实现代码如下:

@MultipartConfig(location="/", fileSizeThreshold=1024*102,
maxFileSize=1024*1024*5, maxRequestSize=1024*1024*5*5)
@WebServlet(urlPatterns={"/fileUpload"},loadOnStartup=1)
public class FileUpload extends HttpServlet {
    

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("UTF-8");
        String fileName=request.getParameter("username")+new Date().getTime()+".jpg";

        
        Part part=request.getPart("imageFile");
        part.write(fileName);

        response.setContentType("application/json;charset=utf-8");
        
        String s="{\"result\":\"success\"}";
        response.getWriter().print(s);
    }

}

 

  • 客户端的Ajax上传实现如下,使用FormData进行构建,FormData中的append的方法可以添加二进制和文本数据。二进制数据直接通过获取File对象既可,如:

var formData=new FormData(); formData.append("username",username);formData.append("image",image);

实现代码如下:

 

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/jquery-1.12.0.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
<link href="css/bootstrap.css" rel="stylesheet">
<title>Insert title here</title>
<script>
    $(document).ready(function() {
        $("#imageFile").change(function() {
            var fileReader = new FileReader();
            fileReader.onload = function(e) {
                $("#previewImage").append("<span class='center-block text-success'>图像预览</span><image class='img-thumbnail' style='max-width:400px;height:auto;' src="+e.target.result+"/>");
            }
            var imageFile = this.files[0];
            fileReader.readAsDataURL(imageFile);
        });
        $("#send")
        .click(
                function() {
                        var xhr=new XMLHttpRequest();
                        xhr.open("post","fileUpload");
                        xhr.onreadystatechange = function() {
                            if (xhr.readyState == 4) {
                                if(xhr.status == 200){
                                alert("图片上传成功"); 
                            }else{
                                alert("图片上传失败")
                            }
                            }
                        };
                    var imageFile = $("#imageFile")[0].files[0];
                    var username=$("#username").val();
                    var myForm = new FormData();
                    myForm.append("username",username);
                    myForm.append("imageFile", imageFile);
                    xhr.send(myForm);
                });

    });
</script>
</head>
<body>
    <div class="container">
        <div class="panel">
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">图像上传和预览测试</h3>
                </div>
                <div class="panel-body">
                    <p id="previewImage"></p>
                    <form action="fileUpload" enctype="multipart/form-data"
                        method="post" class="form-inline">
                        <div class="form-group">
                            <label for="username">用户名</label>
                        </div>
                        <div class="form-group">
                            <input type="text" id="username" name="username" />
                        </div>
                        <div class="form-group">
                            <label for="imageFile">上传图片</label>
                        </div>
                        <div class="form-group">
                            <input type="file" id="imageFile" name="imageFile"
                                accept="image/jpeg" />
                        </div>

                        <button type="button" id="send" class="btn btn-primary">上传</button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
posted @ 2016-03-12 00:14  NotOnlyAnAnswer  阅读(2470)  评论(0编辑  收藏  举报