这几天在做项目时有用到一个form表单来上传多个文件,并且要求不能重新刷新。当时在做的时候由于不是很了解这个东西,导致还是走了一些弯路的,现在把代码贴出来,供大家一起交流
html代码
<div id="book" style="display:none; background-color: #F3F3F3;text-align: center;margin-left: 15%;width: 80%;;border: 1;border-radius:15px ">
<h3>书籍上传</h3>
<form action="ResourceTypeAction_uploadFile.action" target="target" method="post" enctype="multipart/form-data" οnsubmit="return toVaild1()">
<input type="hidden" name="resourceTypeId" id="resourceTypeId1">
<table style="text-align: center;width: 100%">
<tr height="35px">
<td width="33%" style="text-align: right;">类别: </td>
<td style="text-align: left;" colspan="2"><select id="category" class='select2' name='cid'>
<option value="0">--请选择--</option></select> <span class="prompt">*</span></td>
</tr>
<tr height="35px">
<td width="33%" style="text-align: center;" >ISBN: <input type="text" name="isbn" id="isbn"/><span class="prompt">*</span> </td>
<td width="33%" style="text-align: left;"> 书名: <input type="text" name="title" id="title"/> <span class="prompt">*</span> </td>
<td width="33%" style="text-align: left;"> 价格: $<input type="text" name="price" id="price"/> </td>
</tr>
<tr height="35px">
<td width="33%" style="text-align: center;">作者: <input type="text" name="author" id="author"/> </td>
<td width="33%" style="text-align: center;">书籍图片: <input type="file" name="imagesUrl" id="imagesUrl" accept="image/*"/> </td>
<td width="33%" style="text-align: center;">书籍PDF:<input type="file" name="pdfsUrl" id="pdfsUrl1"/> <span class="prompt">*</span></td>
</tr>
<tr height="35px">
<td width="33%" style="text-align: center;"> 书籍源码:<input type="file" name="codesUrl" id="codesUrl1"/> </td>
<td width="33%" ><input height="35px" type="submit" value="上传" class="inp_L1" onMouseOver="this.className='inp_L2'" onMouseOut="this.className='inp_L1'"> </td>
</tr>
<tr>
<td colspan="3" style="text-align: left;"><br>书籍描述:</br><textarea rows="30" cols="50" id="editor01" name="description"></textarea></td></tr>
</table>
</form>
<iframe name="target" id="target" frameborder="0" width="0" height="0"></iframe>
</div>
这里有几个地方一定要注意一下
1.target="target" 表示表单在提交完数据后,处理的结果在target指定的iframe里执行,同时我把iframe设置高度和宽带都为0,这样就达到了隐藏的效果,所以这么做就能达到无刷新的效果
2. οnsubmit="return toVaild1()" 这个是表单在点击提交时,会进入toVaild1这个方法里面来校验数据,对于我们来控制提交的数据很有帮助的。一旦那个数据不符合我们的要求
,我们只需要返回一个false就行了,表单在你返回一个false后就不会提交了
3. enctype="multipart/form-data" 这个就不用多说了吧,文件上传必须来这么个东西
toVaild1方法
function toVaild1(){
var val = document.getElementById("category").value;
if(val == "--请选择--"){
alert("请选择一个类别");
return false;
}
}
在表单提交完数据,我们通过下面这个js代码来处理结果
<script>
//通过这个js提示文件是上传成功还是失败
var iframe = document.getElementById("target");
var uploadCallback = function () {
var data=iframe.contentDocument.body.innerHTML;
// "<pre style="word-wrap: break-word; white-space: pre-wrap;">{"obj":"","responseCode":0}</pre>"
var start=data.indexOf("responseCode");//
var num=data.substring(start+14,start+15);//获取响应码
if(num==1||num=="1"){
alert("成功");
}else{
alert("失败")
}
};
iframe.onload = uploadCallback;
</script>
上面这个js代码有个要注意的地方,那个responseCode不是固定的,是你自己封装的状态响应属性!像我就是有写这么个javabean的,responseCode是响应状态,obj是响应内容。所以下面那个截取响应码也是跟大家自己封装的Javabean有关
下面就是action里面处理这个表单数据了
public void uploadFile() throws IOException {
HttpServletRequest request = ServletActionContext.getRequest();
String name=request.getParameter("pdfsUrl");
String imagesUrlname=null;
String pdfsUrlname=null;
String codesUrlname=null;
if(this.imagesUrl!=null && this.imagesUrl!=""){
imagesUrlname=UploadFileUtil.uploadFile(request,new File(this.imagesUrl),this.imagesUrlFileName, "updloadBook");
}
if(this.pdfsUrl!=null && this.pdfsUrl!=""){
pdfsUrlname=UploadFileUtil.uploadFile(request,new File(this.pdfsUrl),this.pdfsUrlFileName, "updloadBook");
}
if(this.codesUrl!=null && this.codesUrl!=""){
codesUrlname=UploadFileUtil.uploadFile(request,new File(this.codesUrl),this.codesUrlFileName, "updloadBook");
}
Book book=new Book();
book.setAuthor(author);
book.setCid(cid);
book.setIsbn(isbn);
book.setTitle(title);
book.setPrice(price);
book.setDescription(description);
book.setPdfsUrl(pdfsUrlname);
book.setImagesUrl(imagesUrlname);
book.setCodesUrl(codesUrlname);
book.setResourceTypeId(resourceTypeId);
book.setEdtionId(edtionId);
book.setSubjectid(subjectid);
book.setSemeter(semeter);
this.resourceTypeBiz.insertInfo(book);
jsonStr = super.writeJson(1, "成功");
try {
} catch (Exception e) {
jsonStr = super.writeJson(0, "失败");
logger.error(e);
}
JsonUtil.jsonOut(jsonStr);
}
说到这里就要说Struts2框架里面有个这么的东西了,在文件上传后,提交到后台的文件其实是个临时文件,那么我们想获得文件的类型和文件名想通过前台传过来的文件来获取这就是不可能的了,因为在临时文件中是得不到这些东西的,所以Struts2框架给我们提供了
// <!--获取上传文件名,命名格式:表单file控件名+FileName(固定)-->
private String imagesUrlFileName;
这么东西,它的格式是固定的,只需要在action的属性里面加上一个file的name值+FileName就行了,它就能在表单提交后自动注入提交的文件名,除此之外,Struts1还有提供一个获取文件类型的东西
//获取上传文件类型,命名格式:表单file控件名+ContentType(固定)
private String imagesUrlContentType;
通过上面的代码我们也看到了,我有调用了一个工具类的方法,
下面就是那个工具类的方法
public class UploadFileUtil {
/**
*
* @param request http请求,用来获取服务器的路径
* @param file 要保存的临时文件
* @param fileName 要上传文件的原来名字
* @param picRootName 要上传文件保存在webapps下面那个文件夹下
* @author Administrator
* @return
*/
public static String uploadFile(HttpServletRequest request,File file, String fileName,String picRootName) {
String newFileUrl=null;
Map<String, UploadFile> map = new HashMap<String, UploadFile>();
// request.getSession().getServletContext().getRealPath("/") => C:\tomcat\apache-tomcat-7.0.47\webapps\douban
// getParentFile() => E:\apache-tomcat-8.0.44-windows-x64\apache-tomcat-8.0.44\webapps
File webappsfile = new File(request.getSession().getServletContext().getRealPath("/")).getParentFile();
File picFile = new File(webappsfile, picRootName);
String picBasePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ "/" + picRootName;
String originalFilename=fileName;
// 生成新文件名,与时间相关
String newfilename = getUniqueFileName()
+ originalFilename.substring(originalFilename.lastIndexOf("."));
String saveDir = picFile.getAbsolutePath() + getNowDateStr();
String newFilePath = saveDir + newfilename;
// http://localhost:8080/updloadBook/2017/8/22/**.txt
newFileUrl = picBasePath + getNowDateStr() + newfilename;
File saveDirFile = new File(saveDir);
if (!saveDirFile.exists()) {
saveDirFile.mkdirs();
}
String path=saveDir+ java.io.File.separator+newFileUrl;
try {
//输出流 http://localhost:8080/updloadBook/2017/8/22/3413dba067d74a37b7e7e11060dcab03.tmp
OutputStream os = new FileOutputStream(newFilePath);
//输入流
InputStream is = new FileInputStream(file);
byte[] buf = new byte[1024];
int length = 0 ;
while(-1 != (length = is.read(buf) ) )
{
os.write(buf, 0, length) ;
}
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
return newFileUrl;
}
/**
* 如果一个文件夹下面保存超过1000个文件,就会影响文件访问性能,所以上传的文件要分散存储, 这里用年月日作为目录层级 * 获取当前日期字符串
* * @param separator * @return "/2017/2/20/"
*/
private static String getNowDateStr() {
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH) + 1;
int day = now.get(Calendar.DATE);
// / / /
//return File.separator + year + File.separator + month + File.separator + day + File.separator;
return "/"+year+"/"+month+"/"+day+"/";
}
/**
* 生成唯一的文件名
*
* @return
*/
private static String getUniqueFileName() {
String str = UUID.randomUUID().toString(); //444ffdd-333dd -666-666
return str.replace("-", "");
}
}
就这样,文件就上传成功了,并且通过前台的那个处理表单提交的js来得知文件是否上传成功和失败了!