今天在做文件的上传下载,虽然简单,但还是遇到狠多问题。在这记录一下。
1、先说文件的上传。前台jsp使用的是easyUI filebox来做控件,其实就是简单的一个input框。
<input class="easyui-filebox" name="file"
data-options="prompt:'Choose a file...'" style="width: 100%">
然后放在一个表单里,提交表单。
2、后台,后台通过直接获取文件对象,文件名然后通过apache的jar包拷贝文件到指定目录,就可以了,但请注意,在这里将会遇到一个问题。
当我们通过getParameter(“file”);file为前端的name属性的值。获取一个
file对象,我们通过debug会发现,file的文件路径,文件名都与我们上传的文件有很大的区别,可以发现这个文件是一个临时文件,这就是说,我们不能使用file.getName()的方法获取文件名了,因为那不是真正的文件。
虽然上面的这个临时文件不影响我们上传,不过当我们上传要创建一个文件用于拷贝,所以需要用到文件类型,或者我们需要存储上传文件的文件名,这时就需要获取文件名了。使用file.getName(),很遗憾,这是错的,不要担心,我们可以直接getFileName(“file”);获取。
获取到文件名了,也有文件对象,直接使用File.copyFile(srcFIle,destFile)就解决了文件上传。
下满是代码片段:
创建一些工具类:
RequestUtils用于装载参数,这个例子,请看getFile,getFileName 的方法。
/*##########################################/
/*##########################################/
/*##########################################/
package com.ulwx.tool;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
public class RequestUtils
{
private Map<String, Object[]> rParms = new HashMap<String, Object[]>();
private Map<String, Object[]> objs = new HashMap<String, Object[]>();
private static Logger log = Logger.getLogger(RequestUtils.class);
public RequestUtils(Map requestParameters)
{
rParms = requestParameters;
}
public RequestUtils()
{
rParms = new HashMap<String, Object[]>();
}
public void setString(String name, String value)
{
rParms.put(name, new String[] { value });
}
public void setStrings(String name, String[] values)
{
rParms.put(name, values);
}
public Map<String, Object[]> getrParms()
{
return rParms;
}
public void setrParms(Map<String, Object[]> rParms)
{
this.rParms = rParms;
}
public void setInt(String name, Integer value)
{
rParms.put(name, new String[] { value + "" });
}
public void setFloat(String name, Float value)
{
rParms.put(name, new String[] { value + "" });
}
public void setDouble(String name, Double value)
{
rParms.put(name, new String[] { value + "" });
}
public void setObject(String name, Object value)
{
objs.put(name, new Object[] { value });
}
public void setObjects(String name, Object[] values)
{
objs.put(name, values);
}
public Object getObject(String name)
{
try
{
Object value = ArrayUtils.getFirst((Object[]) objs.get(name));
if (value == null)
return null;
return value;
} catch (Exception e)
{
return null;
}
}
public Object[] getObjects(String name)
{
try
{
Object[] value = (Object[]) objs.get(name);
return value;
} catch (Exception e)
{
// log.error("", e);
return null;
}
}
public String getString(String name)
{
try
{
String value = ArrayUtils.getFirst((String[]) rParms.get(name));
if (value == null)
return "";
return value;
} catch (Exception e)
{
return null;
}
}
public File getFile(String name)
{
try
{
File value = ArrayUtils.getFirst((File[]) rParms.get(name));
return value;
} catch (Exception e)
{
// log.error("", e);
return null;
}
}
public String getFileContentType(String name)
{
return this.getString(name + "ContentType");
}
public String[] getFileContentTypes(String name)
{
return this.getStrings(name + "ContentType");
}
public String getFileName(String name)
{
return this.getString(name + "FileName");
}
public String[] getFileNames(String name)
{
return this.getStrings(name + "FileName");
}
public File[] getFiles(String name)
{
try
{
return (File[]) rParms.get(name);
} catch (Exception e)
{
// log.error("", e);
return null;
}
}
public Integer getInt(String name)
{
String value = ArrayUtils.getFirst((String[]) rParms.get(name));
if (value == null)
return null;
try
{
return Integer.parseInt(value);
} catch (Exception e)
{
// log.error("", e);
return null;
}
}
public Float getFloat(String name)
{
String value = ArrayUtils.getFirst((String[]) rParms.get(name));
if (value == null)
return null;
try
{
return Float.parseFloat(value);
} catch (Exception e)
{
// log.error("", e);
return null;
}
}
public Double getDouble(String name)
{
String value = ArrayUtils.getFirst((String[]) rParms.get(name));
if (value == null)
return null;
try
{
return Double.parseDouble(value);
} catch (Exception e)
{
// log.error("", e);
return null;
}
}
public Byte getByte(String name)
{
String value = ArrayUtils.getFirst((String[]) rParms.get(name));
if (value == null)
return null;
try
{
return Byte.parseByte(value);
} catch (Exception e)
{
// log.error("", e);
// TODO Auto-generated catch block
return null;
}
}
public Boolean getBoolean(String name)
{
String value = ArrayUtils.getFirst((String[]) rParms.get(name));
if (value == null)
return null;
try
{
return Boolean.valueOf(value);
} catch (Exception e)
{
// log.error("", e);
return null;
}
}
public String[] getStrings(String name)
{
try
{
String[] value = (String[]) rParms.get(name);
return value;
} catch (Exception e)
{
// log.error("", e);
return null;
}
}
public void setInts(String name, Integer[] values)
{
rParms.put(name, ArrayUtils.toStringArray(values));
}
public void setBoolean(String name, Boolean value)
{
rParms.put(name, new String[] { value + "" });
}
public void setBooleans(String name, Boolean[] values)
{
rParms.put(name, ArrayUtils.toStringArray(values));
}
public void setBytes(String name, Byte[] values)
{
rParms.put(name, ArrayUtils.toStringArray(values));
}
public void setByte(String name, Byte value)
{
rParms.put(name, new String[] { value + "" });
}
public Date getDayDate(String name)
{
String value = ArrayUtils.getFirst((String[]) rParms.get(name));
if (value == null)
return null;
try
{
return CTime.parseDayDate(value);
} catch (Exception e)
{
return null;
}
}
public Date[] getDayDates(String name)
{
String[] value = (String[]) rParms.get(name);
if (value == null)
return null;
Date[] res = new Date[value.length];
for (int i = 0; i < value.length; i++)
{
try
{
res[i] = CTime.parseDayDate(value[i]);
} catch (Exception e)
{
res[i] = null;
}
}
return res;
}
public void setWholeDate(String name, Date value)
{
String str = CTime.formatWholeDate(value);
rParms.put(name, new String[] { str });
}
public void setWholeDates(String name, Date[] values)
{
String[] strs = new String[values.length];
for (int i = 0; i < strs.length; i++)
{
try
{
strs[i] = CTime.formatWholeDate(values[i]);
} catch (Exception e)
{
strs[i] = null;
}
}
rParms.put(name, strs);
}
public Date getWholeDate(String name)
{
String value = ArrayUtils.getFirst((String[]) rParms.get(name));
if (value == null)
return null;
try
{
return CTime.parseWholeDate(value);
} catch (Exception e)
{
return null;
}
}
public Date[] getWholeDates(String name)
{
String[] value = (String[]) rParms.get(name);
if (value == null)
return null;
Date[] res = new Date[value.length];
for (int i = 0; i < value.length; i++)
{
try
{
res[i] = CTime.parseWholeDate(value[i]);
} catch (Exception e)
{
res[i] = null;
}
}
return res;
}
public Integer[] getInts(String name)
{
String[] value = (String[]) rParms.get(name);
if (value == null)
return null;
Integer[] res = new Integer[value.length];
for (int i = 0; i < value.length; i++)
{
try
{
res[i] = Integer.parseInt(value[i]);
} catch (Exception e)
{
// TODO Auto-generated catch block
// log.error("", e);
res[i] = null;
}
}
return res;
}
public Boolean[] getBooleans(String name)
{
String[] value = (String[]) rParms.get(name);
if (value == null)
return null;
Boolean[] res = new Boolean[value.length];
for (int i = 0; i < value.length; i++)
{
try
{
res[i] = Boolean.valueOf(value[i]);
} catch (Exception e)
{
// TODO Auto-generated catch block
res[i] = null;
}
}
return res;
}
public Byte[] getBytes(String name)
{
String[] value = (String[]) rParms.get(name);
if (value == null)
return null;
Byte[] res = new Byte[value.length];
for (int i = 0; i < value.length; i++)
{
try
{
res[i] = Byte.parseByte(value[i]);
} catch (Exception e)
{
// TODO Auto-generated catch block
res[i] = null;
}
}
return res;
}
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
RequestUtils ru = new RequestUtils();
ru.setBooleans("sss", new Boolean[] { true, false });
System.out.println(ArrayUtils.toJsonString(ru.getBooleans("sss")));
}
}
/*############################################/
/*############################################/
/*############################################/
在baseAction 中加入这一段
/**
* 从请求中取出参数,又将参数放回请求中
*
* @param ctx
* @return
*/
@SuppressWarnings("rawtypes")
public RequestUtils getRequestUtils() {
ActionContext ctx = ActionContext.getContext();
Map<String, Object> rParms = ctx.getParameters();
RequestUtils ru = new RequestUtils((Map)rParms);
return ru;
}
/*############################################/
/*############################################/
/*############################################/
在action中加入代码片段
public String upload()
{
ActionContext ctx = ActionContext.getContext();
RequestUtils ru = this.getRequestUtils();
File[] files = ru.getFiles("file"); //根据文件参数获取文件
String[] fileNames = ru.getFileNames("fileName"); //根据文件参数获取文件名
String[] result = null;
try
{
if (files != null && files.length > 0)
{
result = FileUtil.uploadFiles(files, fileNames); //上传文件
}
logger.info("上传文件完成!!");
ctx.put("json", "ok");
}
catch (Exception e)
{
logger.error("上传文件失败!!" + e);
ctx.put("json", "error");
}
return "json";
}
/*############################################/
/*############################################/
/*############################################/
上传文件的代码,这里是整个工具类FileUtil,上传只需要看uploadFile方法,GlobalConfig是用于都配置文件的,你也可以自己写一个类用于读配置文件,然后将该类放到监听器中,也可以直接将配置文件在web.xml中配置,然后通过上下文获取配置信息。
package com.ulwxbase.web.action.file;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.UUID;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import com.ulwxbase.utils.DateUtil;
import com.ulwxbase.utils.EmptyUtils;
import com.ulwxbase.utils.GlobalConfig;
/**
* @author lizq E-mail: 825332548@qq.com
* @version 创建时间:2016年7月11日 下午3:23:22
*
* The class is use for ...
*/
public class FileUtil
{
private static final Logger logger = Logger.getLogger(FileUtil.class);
private final static String FILE_UPLOAD_PATH = GlobalConfig.getRealPathProperty("config", "file.upload.path",
"D:testUploadFile/webapps/ROOT/upload");
/**
* 上传单个文件
* @param file 需要上传的文件
* @return 返回上传文件后的路径
*/
public static String uploadFile(File file)
{
String destFilePath = null; //上传文件的路径
if (file != null)
{
String fileName = file.getName(); //获取文件名
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1); //获取文件类型
logger.info("文件名:" + fileName);
logger.info("文件类型:" + fileType);
File dir = new File(createFilePath(fileType)); //构造文件目录
if (!dir.exists()) //不存在文件目录,创建目录
{
dir.mkdirs();
}
// 构造上传文件的路径
destFilePath = createFilePath(fileType) + File.separator + createFileName() + "." + fileType;
logger.info("上传文件路径:" + destFilePath);
copyFile(file, new File(destFilePath)); //将原文件复制到目标文件
}
return destFilePath; //返回上传文件的路径
}
/**
* 单文件上传,此方法需要文件名,主要用于struts文件上传,struts会将文件放到一个临时存储文件的tmp中,
* 所以不能使用file.getName();方法获取文件名,但struts会把文件名作为参数。
* @param file 文件对象
* @param fileName 文件名
* @return 上传的文件路径
*/
public static String uploadFile(File file, String fileName)
{
String destFilePath = null; //上传文件的路径
if (file != null && !EmptyUtils.isEmptyString(fileName))
{
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1); //获取文件类型
logger.info("文件名:" + fileName);
logger.info("文件类型:" + fileType);
File dir = new File(createFilePath(fileType)); //构造文件目录
if (!dir.exists()) //不存在文件目录,创建目录
{
dir.mkdirs();
}
// 构造上传文件的路径
destFilePath = createFilePath(fileType) + File.separator + createFileName() + "." + fileType;
logger.info("上传文件路径:" + destFilePath);
copyFile(file, new File(destFilePath)); //将原文件复制到目标文件
}
return destFilePath; //返回上传文件的路径
}
/**
* 多个文件上传,此方法需要文件名,主要用于struts文件上传,struts会将文件放到一个临时存储文件的tmp中,
* 所以不能使用file.getName();方法获取文件名,但struts会把文件名作为参数。
* @param files 文件对象数组
* @param fileNames 文件名数组
* @return 文件上传的路径数组
*/
public static String[] uploadFiles(File[] files, String[] fileNames)
{
String filePath[] = new String[fileNames.length];
for (int i = 0; i < files.length; i++)
{
filePath[i] = uploadFile(files[i], fileNames[i]);
}
return filePath;
}
/**
* 下载文件
* @param srcPath 需要下载的文件的路径
* @param fileName 下载文件的文件名
* @param response 响应对象,用于设置文件的响应头
* @throws Exception
*/
/**
* 下载文件
* @param srcPath 需要下载的文件的路径
* @param fileName 下载文件的文件名
* @param response 响应对象,用于设置文件的响应头
* @return Boolean 下载文件失败,return false ,otherwise true
*/
public static Boolean downloadFile(String srcPath, String fileName, HttpServletResponse response)
{
logger.debug("下载文件开始。。。");
logger.info("下载文件路径:" + srcPath + " " + "下载文件名:" + fileName);
OutputStream out = null;
try (BufferedInputStream bufferStream = new BufferedInputStream(new FileInputStream(srcPath)))
{
response.reset();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;fileName="
+ new String(fileName.getBytes("UTF-8"), "ISO8859-1"));
out = response.getOutputStream();
copy(bufferStream, response.getOutputStream());
closeQuietly(bufferStream);
logger.debug("下载文件结束。。。");
}
catch (Exception e)
{
logger.error("下载文件出现异常", e);
return false;
}
finally
{
try
{
out.flush();
out.close();
}
catch (IOException e)
{
}
}
return true;
}
/**
* 下载文件
* @param file 需要下载的文件对象
* @param response 响应对象,用于设置文件的响应头
*/
public static void downloadFile(File file, String fileName, HttpServletResponse response)
{
if (file != null)
{
InputStream in = null;
OutputStream os = null;
try
{
os = response.getOutputStream();
response.setContentType("application/x-download; charset=utf-8");
response.setHeader("Content-disposition",
"attachment; filename=" + new String(fileName.getBytes("UTF-8"), "ISO8859-1"));
in = new BufferedInputStream(new FileInputStream(file));
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = in.read(buffer, 0, 8192)) != -1)
{
os.write(buffer, 0, bytesRead);
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (os != null)
{
try
{
os.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (in != null)
{
try
{
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
in = null;
}
}
}
/**
* 复制文件
* @param srcFile 原文件
* @param destFile 目标文件
*/
public static void copyFile(File srcFile, File destFile)
{
try
{
FileUtils.copyFile(srcFile, destFile);
}
catch (IOException e)
{
logger.error("复制文件失败!!", e);
}
}
/**
* 复制输入输出流,将输入流写到输出流
* @param input 输入流
* @param output 输出流
* @return
* @throws IOException
*/
private static int copy(InputStream input, OutputStream output) throws IOException
{
return IOUtils.copy(input, output);
}
/**
* 关闭流
* @param input
*/
private static void closeQuietly(InputStream input)
{
IOUtils.closeQuietly(input);
}
/**
* 构造上传文件的目录
* @param FileType 文件类型
* @return 文件目录路径
*/
public static String createFilePath(String FileType)
{
return FILE_UPLOAD_PATH + File.separator + FileType + File.separator
+ DateUtil.formatDate("yyyy-MM-dd", new Date());
}
/**
* 构造文件名,使用的是UUID来作为文件名
* @return UUID字符串
*/
public static String createFileName()
{
return UUID.randomUUID().toString();
}
}
上传文件结束,基本的代码都已经贴出来了,主要就是要知道struts上传的文件会放到临时目录中,获取文件对象和获取文件名都可以直接获取。
/*##########################################/
/*##########################################/
/*##########################################/
上传完成,下面就是下载,下载也遇到一个问题,就是
getOutputStream() has already been called for this response
异常,这是问题是在释放在jsp中使用的对象,调用response.getWriter(),因为这个方法是和response.getOutputStream()相冲突的!所以出错。
网上很多例子都是什么out.clear();out = pageContext.pushBody();解决。
但是其实很多时候我们都是在后台做下载,然后返回到jsp,根本就是out。
怎么解决昵?我们在做下载的时候,经常都是表单提交下载文件路径和文件名,根本就不需要返回到jsp的,所以我们在action中return的时候不让他返回到jsp,直接return null;这样就可以解决了。
当然还有一种解决方式,就是在jsp页面调用下载文件的方法。例如我上面的fileUtil的下载文件方法。然后我在action中返回一个jsp页面
public String download()
{
RequestUtils ru = this.getRequestUtils();
String srcPath = ru.getString("srcPath");
String fileName = ru.getString("fileName");
if (!EmptyUtils.isEmptyString(srcPath) && !EmptyUtils.isEmptyString(fileName))
{
FileUtilProxy.download(new File(srcPath), fileName);
}
return this.DOWNLOAD;
}
/*##########################################/
/*##########################################/
/*##########################################/
jsp的代码
<%@page import="com.ulwxbase.utils.MyConstants"%>
<%@page import="java.io.File"%>
<%@page import="com.ulwxbase.web.action.file.FileUtil"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<%
File file = (File) request.getAttribute(MyConstants.Action.URL_DOWNLOAD);
String fileName = (String) request.getAttribute("fileName");
FileUtil.download(file, fileName);
%>
这样也是可以解决这个getOutputStream()异常的。
下载也到这完成。
/*##########################################/
/*##########################################/
/*##########################################/
小结:其实上传下载很简单,但是要注意几个问题:
1、上传要注意临时文件的问题,文件名和文件对象可以直接get出来。
2、下载要注意getOutputStream()问题,我们在做下载的时候一是直接return null可以解决,另一种方式是返回到jsp页面去做,也不会出现异常,还是一种就是网上很多帖子的out.clear();out = pageContext.pushBody();解决。这一种我们试过,所以不知道效果如何。