通常我们会有一个统一的上传接口,这个接口会被其他的服务调用.如果出现不同域,还需要无刷新上传文件,并且获取返回值,这就有点麻烦了.比如,新浪微博启用了新域名www.weibo.com,但接口还是使用原来的域:picupload.t.sina.com.cn.
研究了一下新浪微博的处理方法.
首先是一个正常的上传页面 upload.jsp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<%@ 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">
<html>
<head>
<title>Upload</title>
</head>

<script type="text/javascript">

//上传完成后被回调的函数
function cburl(filenames){

alert("—————-"+filenames);
}

</script>

<body>
<form name="uploadForm" method="POST" enctype="MULTIPART/FORM-DATA"
action="http://upload.file.com/http/fileupload" target="cb_iframe">

<!-上传成功后被回调的URL,主要用于跳转到本域 ->
<input type="hidden" name="cburl" value="http://127.0.0.1:8080/crossupload/cburl.jsp" />
<table>
<tr>
<td>
<div align="right">
User Name:
</div>
</td>
<td>
<input type="text" name="username" size="30" />
</td>
</tr>
<tr>
<td>
<div align="right">
Upload File1:
</div>
</td>
<td>
<input type="file" name="file1" size="30" />
</td>
</tr>

<tr>
<td>
<input type="submit" name="submit" value="upload">
</td>
<td>
<input type="reset" name="reset" value="reset">
</td>
</tr>
</table>
</form>
<IFRAME id="cb_iframe" name="cb_iframe" src="about:blank" frameborder='0'></IFRAME>
</body>
</html>

这里有一个关键点是form的target要指向iframe,同时把iframe隐藏起来,这样上传的处理结果就会显示在该iframe里.隐藏域里的cburl(callback)参数表示处理完成后要跳转的url,因为我们的目标是iframe,所以只会把跳转的页面输出到iframe,而不会让当前页面跳转.

还有一点,callback url要和当前页面同域.跨域的iframe无法调用父页面的内容.

再来看看fileupload,也就是form的action 是个servlet

1
cburl = cburl + "?" + "filenames=" + URLEncoder.encode(fileNames.toString(), "UTF-8");

这里可以处理文件,然后入库.操作完成后,把文件的id及其他信息都放在url里,最后跳转到这个url.

最后来看看cburl.jsp,也就是刚刚fileupload跳转到的url,这个文件的内容会填充到页面的iframe里.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<%
String cburl=new String(request.getParameter("filenames").getBytes("ISO-8859-1"),"UTF-8");

%>
<html>
<script type="text/javascript">
window.parent.cburl("<%=cburl%>");
</script>
<body>
</body>
</html>

这里调用了父窗口的cburl方法,这样父页面就获得了文件的id.