写了一个简单的类似ajax上传文件的功能,原理当然不是真正的通过ajax方式上传,而是利用iframe来做的
这是其中的一种写法:
先来分析一下原理,利用js来创建一个iframe,这个iframe的src指向一个静态页面。这个静态页面当中有一个Form表单
进行提交。后台提交成功后让其运行一个父窗口的js函数,并返回上传成功的文件路径、
?
先来看js,由于有一些参数是可变的,所以代码上有些混杂.(程序当中为方便,用到了jquery框架)
?
var Upload = {}; Upload = { formId:"D_upload_form", imgURL : "http://www.xxxx.com:8080/img", action : "/img/upload.htm", currentFilePath:null, allFilePath:new Array(), imgPreDiv:null, uploadInfo:null, checkType:2,//默认检测类型为图片格式 imgTemplate:null, //图片显示模板格式 maxNum:5, //最大上传数量 hasUploadNum:0,//已经上传的数量 /** * 如果需要修改默认参数调用此方法. */ setting:function(uploadURL, upladAction, checkType) { Upload.imgURL = uploadURL || Upload.imgURL; Upload.action = upladAction || Upload.action; Upload.checkType = checkType || Upload.checkType; }, /** * 创建文件上传 * @param fileID 当前file控件ID * @param imgListDivId 如果是图片,则可设置图片上传完成后显示的缩略图的位置 * @param infoId 提示用户正在上传的信息所在的标签ID * @param imgTemplate 图片上传后显示的的格式模板,程序根据此模板自动生成后续的图片样式 */ createUpload:function(fileID, imgListDivId, infoId, imgTemplate) { if (typeof($) != "function") { alert("请导入jquery1.2.6以上版本JS文件"); return; } var fileInput = $("#" + fileID); var iframeWidth = fileInput.parent().css("width") || "250"; var iframeHeight = fileInput.parent().css("height") || "30"; var html = "<iframe frameborder='0' id='D_upload_iframe' scrolling='no' src='" + Upload.imgURL + "/html/upload.html' width='" + iframeWidth + "' height='" + iframeHeight + "'></iframe>"; fileInput.parent().html(html); if (imgListDivId != null || imgListDivId != "") { Upload.imgPreDiv = $("#" + imgListDivId); } if (infoId != null || infoId != "") { Upload.uploadInfo = $("#" + infoId); } if (imgTemplate != null || imgTemplate != "") { Upload.imgTemplate = $("#" + imgTemplate).html(); } }, /** * 供后台程序调用,设置当前上传成功的文件路径 * @param path 上传后的路径 */ setFilePath:function(path) { Upload.currentFilePath = path; Upload.allFilePath.push(path); //var img = "<img src='" + path + "' alt='上传的图片,可删除'/>"; var img = Upload.imgTemplate.replace("src=\"\"", "src=\"" + path + "\""); if (Upload.imgPreDiv != null) { Upload.imgPreDiv.append(img); } history.back(); Upload.uploadInfo.hide(); }, /** * 供后台程序调用,当上传出现错误时弹出错误提示框 * @param error 错误信息 */ uploadError:function(error) { alert(error); history.back(); Upload.uploadInfo.hide(); }, /** * 获取当前上传的文件路径 */ getFilePath:function() { return Upload.currentFilePath; }, /** * 显示正在上传信息 */ showUploadInfo:function() { Upload.uploadInfo.show(); } };
上面的JS?方法基本没什么可说的,通过获取当前页面当中的一个input对象,将其替换成一个iframe并保留一些参数
?
?
下面来看iframe静态页面内容:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title></title> <meta http-equiv="Content-type" content="text/html;chartset=utf-8"/> </head> <body style="padding:0;"> <form style="padding:0;" method="post" action="" enctype="multipart/form-data"> <input type="file" name="fileName" onchange="listernInputChange(this,this.form);"/> </form> </body> <script type="text/javascript"> function iframeLoad() { if (parent.Upload == null || parent.Upload == "undefined") { alert("您的设置可能问题,或访问了不该的页面!"); history.back(); } else { document.forms[0].action = parent.Upload.imgURL + parent.Upload.action; } } function listernInputChange(input, form) { var form1 = form || document.forms[0]; var pattern = /\.(jpg|jpeg|gif|bmp|png)(\s|$)/i; if (parent.Upload.checkType == 1) { pattern = /\.(css)(\s|$)/i; } else if (parent.Upload.checkType == 3) { pattern = /\.(swf)(\s|$)/i; } var url = input.value; if (parent.Upload.hasUploadNum < parent.Upload.maxNum) { if (!pattern.test(url)) { alert("上传的文件格式不正确"); } else { parent.Upload.showUploadInfo(); form1.submit(); } parent.Upload.hasUploadNum++; } else { alert("已达到最大上传数量,不可以再上传"); } } iframeLoad(); </script> </html>
iframe页面当中,做了如下事:
1:获取父窗口当中传入的action路径
2:获取用户设置的最大上传数量及上传的文件类型
3:监听浏览按钮的change事件进行表单提交
整个页面调用了父窗口当中的JS函数来获取相关的参数
?
现在来看后台代码:
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
String imgPath = "";
String sectionPath = "";
String fileName = "";
StringBuffer uploadError = null;
try {
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
//获取当前项目所在的绝对路径
if (DStringUtil.isEmpty(UploadCtrl.CONTEXT_PATH)) {
UploadCtrl.CONTEXT_PATH = request.getSession().getServletContext().getRealPath("/");
}
//文件保存路径
String path = request.getParameter("savePath");
//检测类型
String checkType = request.getParameter("checkType");
//默认检测的文件类型为图片格式,可以设置指定类型
byte cType = UploadUtil.IMG_TYPE;
if (DStringUtil.isEmpty(path)) {
path = ConfigUtil.DEFAULT_IMG_PATH;
}
if ((!DStringUtil.isEmpty(checkType)) && DStringUtil.isNumber(checkType)) {
cType = Byte.valueOf(checkType);
}
sectionPath = UploadCtrl.CONTEXT_PATH + path;
uploadError = new StringBuffer(); //保存上传当中的错误信息,有错误时,不回滚
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("fileName");
if (file.getSize() > 0) {
String error = UploadUtil.checkFileExt_SIZE(file, cType, ConfigUtil.MAX_IMG_50K);
if (DStringUtil.isEmpty(error)) {
imgPath = UploadUtil.uploadTempFile(sectionPath, file, CreateCode.getCode());
fileName = imgPath;
imgPath = imgURL + path + "/" + imgPath;
}
uploadError.append(error);
}
if (uploadError.length() == 0) {
//插入图片
out.println("<html>");
out.println("<head>");
out.println("<title>Insert Image</title>");
out.println("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">");
out.println("</head>");
out.println("<body>");
out.println("<script type=\"text/javascript\">parent.Upload.setFilePath(\"" + imgPath + "\")</script>");
out.println("</body>");
out.println("</html>");
} else {
out.println("<html>");
out.println("<head>");
out.println("<title>error</title>");
out.println("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">");
out.println("</head>");
out.println("<body>");
out.println("<script type=\"text/javascript\">parent.Upload.uploadError(\"" + uploadError.toString() + "\");</script>");
out.println("</body>");
out.println("</html>");
}
} catch (Exception e) {
logger.error("上传图片:" + e);
if (!DStringUtil.isEmpty(imgPath)) {
UploadUtil.deleteFile(sectionPath + "/" + fileName);
}
throw e;
} finally {
if (uploadError != null && !DStringUtil.isEmpty(uploadError.toString())) {
UploadUtil.deleteFile(sectionPath + "/" + fileName);
}
}
return null;
}
?
以上代码当中用了一些工具类,在这里并未给出,重点的是看后面上传成功后如果让其将路径返回给父窗口
查看其中的红色代码,这里利用response写入一段代码,并让其运行父窗口当中的方法,通过传参的方式,将文件路径告之父窗口。
?
来看演示HTML:
<script type="text/javascript"> $(function() { //创建上传文件,及处理上传成功后的操作 Upload.createUpload("imgFile", "imgList", "D_upload_label_info", "ImageTemplate"); //Upload.createUpload("imgFile2", "imgList2", "", ""); }); </script> <%--图片显示模板格式--%> <div id="ImageTemplate"> <div> <img src="" alt="图片位置"/></div> </div> <%--图片显示位置--%> <div id="imgList" style="height:150px;"> </div> <div style="height:30px;"> <%--只是一个占位符--%> <input id="imgFile" type="file" name="imgFile"/> </div> <div> <label id="D_upload_label_info" style="display:none;">正在上传....</label> </div> <div> <input id="imgFile2" type="file" name="imgFile"/> </div> <%--图片显示位置--%> <div id="imgList2" style="height:150px;"> </div>
?
?
?
以上就是整个上传的过程。
不足之处:目前在同一个页面只能有一个上传的文件选择框,不能有多个不同提交路径及不同参数的上传框。
?
?
?