由于项目有一个身份证验证的注册界面,所以要上传图片。但在注册界面填写完信息后,用户选择本地图片上传预览,要实现不更新界面显示。所以开始最先想到的是用js获取本地文件的路径然后显示,无奈js标准考虑到用户文件的安全,不提供接口。其实这样最好,至少保证了用户的隐私。不严格来说,其实是有接口的,早前的ie6有接口直接获取用户本地文件的路径,但是ie9以后我没找到。谷歌最新版好像也不提供,别的浏览器也有各种版本,但是兼容性太差了,一百个哈姆雷特……所以只能放弃js。
转之考虑我只能朝另外一个方面想问题了,也就是想到先上传到服务器,然后再获取图片在服务器的路径显示在html上,人人网的头像就是先上传到服务器再处理的,不过新浪和腾讯微博我看了一下,好像有flash控件先在本地预览再上传到服务器,不过对于flash,我一窍不通。
考虑到要无刷新局部修改页面,当然想到现在最火的ajax,这个我看了一下,也用servlet写了几个传送文本例子,感觉效果不错。然后今天晚上试着写代码上传图片然后局部更新,无奈代码都写好了,最后测试的时候,发现一直显示不出来图片,google里面百度了一下:是这么说的“众所周知ajax是使用了浏览器内部的XmlHttpRequest对象来传输XML数据的。既然是Xml的数据传输,那么传输的数据肯定是文本的,而文件上传则需要传输二进制的数据,显然用ajax是不可能的。”显然我对ajax的理解只是在皮毛阶段,看来凡事得三思后行,否则浪费时间。
没办法了,试过好几种方法还解决不了问题,最后只能用今天早上看到的一种方法,我不是很理解,所以一直没有深入研究。哈哈,熬夜学了一下,终于解决我的问题了……介绍一下这个东东:其实在ajax出现之前,web应用也可以是无刷新的,那时大多通过IFrame来做到这一点。当然Ajax出现之后,人们一窝蜂地投奔Ajax 的阵营了,iFrame 就乏人问津了。但是用iFrame来实现无刷新上传文件确实一个很好的选择。ps:Ajax技术基本上可以说是由google公司带起来的,但少Gmail中上传文件用的还是 IFrame,所以说使用IFrame来上传文件是最好的选择。
夜深了~上测试效果和代码给大伙瞅瞅:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~点击选择文件后直接触发按钮上传图片到服务器,然后返回图片地址给当前页面
这是表单页面,也就是上面显示的页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>upload images</title>
<style type="text/css">
body {
background-color: #A4EAF4;
margin:0px
color:#000;
font-size:12px;
}
#main{
margin:0 auto;
width:900px;
height:500px;
position:relative;
}
.images{
position:absolute;
top:100px;
left:350px;
width:200px;
height:200px;
margin:0 auto;
background-color:#FFFFFF
}
</style>
<script type="text/javascript">
function change(){
document.form1.submit();
}
</script>
</head>
<body>
<div id="main">
<div class="images">
<div style="width:180px;margin:0 auto;color:#E6444E;font-size:18px;"><span>请选择本地头像上传</span></div>
<div>
<form action="upload.jsp" id="form1" name="form1"
encType="multipart/form-data" method="post" target="hidden_frame">
<input type="file" id="file" name="file" style="width:450" οnchange="change();" /> <INPUT
type="submit" value="上传文件" style="display:none;"> <br>
<iframe name='hidden_frame' id="hidden_frame" style='display:none'></iframe>
</form>
</div>
<div id="msg" style="margin:0 auto;width:130px;background-color:#CADF60;height:130px;"></div>
</div>
</div>
<script type="text/javascript">
function callback(msg)
{
var pho="<%=basePath + "upload/"%>" + msg;
//alert(pho);
document.getElementById("file").outerHTML = document
.getElementById("file").outerHTML;
document.getElementById("msg").innerHTML = "<img src='"+pho+"' width=130 height=130/>";
}
</script>
</body>
</html>
index.html 中主要要做的就是写一个 form 和 iframe ,并把 form 的 target 设为 iframe 的名字,注意要把 iframe 设为不可见,其他的都是正常的文件上传的写法,这样刷新的页面就是这个隐藏的 Iframe ,而在 index.html 中是不会有页面刷新的,js的 callback 方法是回调方法。用于清空文件上传框和显示后台信息,注意清空文件上传框的方法,和普通方法有点不一样。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这是处理上传图片到服务器的界面,由于只是测试我都写在jsp上面了
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page import="com.jspsmart.upload.SmartUpload"%>
<%@page import="com.jspsmart.upload.Request"%>
<%@page import="java.io.File"%>
<%
//用于保存返回的文件名
String url1 = "";
//新建一个smartUpload对象
SmartUpload su = new SmartUpload();
//上传初始化
su.initialize(pageContext);
// 设定上传限制
//1限制每个上传文件的最大长度
su.setMaxFileSize(10000000);
//2.限制总上上传数据的长度
su.setTotalMaxFileSize(20000000);
//3.设置允许上传的文件(通过扩展名限制)
su.setAllowedFilesList("jpg,gif,BMP,png");
boolean sign = true;
//4.设定进制上传的文件
try {
su.setDeniedFilesList("exe,bat,jsp,htm,html");
//上传文件
su.upload();
//创建自己的Request 对象
Request myRequest = su.getRequest();
//得到名称
String name = myRequest.getParameter("name");
//得到文件后缀
String ext = su.getFiles().getFile(0).getFileExt();
//组成自定义的文件名称
//MyPathUtil util = new MyPathUtil();
String fileName = "1." + ext;
//将上传文件保存到指定目录
//创建保存文件的文件夹
File file = new File(getServletContext().getRealPath("/")
+ "upload//");
if (!file.exists() && !file.isDirectory()) {
file.mkdir();
}
url1 = fileName;
su.getFiles()
.getFile(0)
.saveAs(getServletContext().getRealPath("/")
+ "upload//" + fileName);
//System.out.println(url1);
} catch (Exception e) {
e.printStackTrace();
sign = false;
}
if (sign == true) {
out.println("<script>parent.callback('" + url1 + "')</script>");
} else {
out.println("<script>parent.callback('upload file error')</script>");
}
%>
注意要在我们的web项目下面WEB-INF/lib 下加上必须的 jspSmartUpload.jar 包;
upload.jsp 中只要注意最后输出的格式就可以了。其实原理就是输出一段js代码到 iframe 中,然后在iframe中来控制它的父页面。
说明有这么一段“ 需要说明的是使用Iframe来上传,状态栏还是会有刷新的,因为iframe 中的页面刷新了嘛,但是外部页面,就是你所看到的页面是没有刷新的,所以也可以说是类似Ajax上传。”
但也仅只是刷新,地址不变,界面内容也是你想要的局部更新…