您的位置:首页 > 编程语言 > Java开发

java上传文件跟批量下载文件(转)

2014-02-11 11:05 369 查看
最近的项目中涉及到文件的上传跟下载的问题,就自己所涉及到的方面做出如下表述。

  首先是文件上传部分,项目的要求是通用性较好,所以只需要传入目标路径即可。参数的传递通过Form表单传值,在目标路径下新建一个File类型的文件,然后通过流的方式将需要上传的文件写入新建的文件中。此方法适用于web开发过程中上传文档类的文件,如果你文件过大请研究ftp相关的知识,笔者所接触的ftp传文件限于C#中,这里不做表述。具体代码如下:

public void fileUpload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String filePath = new String();
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=GB2312");
try
{
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置缓存中最大允许缓存为2M
factory.setSizeThreshold(2 * 1024 * 1024);
ServletFileUpload upload = new ServletFileUpload(factory);
//解决中文文件名为乱码的问题
upload.setHeaderEncoding("UTF-8");
List<FileItem> fileList = upload.parseRequest(request);
Iterator iter = fileList.iterator();
String newFileName = "";
while (iter.hasNext())
{
//获取文件
FileItem fileItem = (FileItem)iter.next();
//获取文件上传的路径
String typeName = fileItem.getFieldName();
if(("destPath").equals(typeName))
{
filePath = fileItem.getString("utf-8");
}
if(("filename").equals(typeName))
{
newFileName = fileItem.getString("utf-8");
}
String fileName = new String();
if (!fileItem.isFormField())
{
String name = fileItem.getName();
if(StringUtil.isNullOrEmpty(name))
{
continue;
}
fileName = name;
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
File file = new File(filePath);
if(!file.exists())
{
file.mkdirs();
}
//向指定的路径写文件
if(newFileName.length()>0)
{
fileName = newFileName;
}
fileItem.write(new File(filePath, fileName));
}
}
}
catch (Exception ex)
{
throw new ServletException("上传文件失败!", ex);
}
}


第二部分是关于文件批量下载的文档。根据客户的观点有上传就要下载的需求,一开始也做了相关的开发,结果发现下载时的文件全部存在服务器端,跟需求不一致。仔细推敲了下代码原来自己写的有问题,在客户端是选择文件的存储路径,然后将文件下载,其实只是实现了本地的迁移,并没有在把文件下载到客户端。后来的想法是把文件打包下载,用FileOutputStream,实现下载的问题,可是如果下载的文件中含有中文字符,就会出现乱码。不得已百度了下,原来是编码的问题,使用java自带的文件输出类不能解决压缩文件中文件名乱码的问题。解决方法:使用ant.jar包,创建压缩文件时,可以设置文件的编码格式,文件名乱码的问题就解决了。由于笔者在开发过程中数据库中有文件的路径,所以下列文件的文件路径的获取是查询得到。

  具体的解决代码如下:

  引用ant.jar包中的FileOutputStream类

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;


打包下载多个文件的思路就是在服务端创建一个新的压缩文件(zip格式),然后将下载的多个文件写入该压缩包中,然后以流的形式输出压缩文件写到客户端,实现下载功能。

public void downloadFiles(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
request.setCharacterEncoding("UTF-8");
String docId = new String(request.getParameter("docId").getBytes("ISO-8859-1"), "UTF-8");
String downloadType = new String(request.getParameter("downloadType").getBytes("ISO-8859-1"), "UTF-8");

Document doc = null;
try
{
doc = getFilePath(docId);  //此方法获取文件的路径,这个不显示
}
catch (SQLException ex)
{
ex.printStackTrace();
}
   
List<Element> elements = doc.getRootElement().elements();
List<File> files = new ArrayList<File>();
int index = 0;
long fileLength = 0;
for(Element ele : elements)
{
String filePath = FormatUtil.tryGetItemText(ele, "FILE_PATH", "") + FormatUtil.tryGetItemText(ele, "FILE_NAME", "");
File file = new File(filePath);
files.add(file);
fileLength += file.length();
index++;
}
String fileName = UUID.randomUUID().toString() + ".zip";
//在服务器端创建打包下载的临时文件
String outFilePath = "C:\\" + fileName;
File file = new File(outFilePath);
//文件输出流
FileOutputStream outStream = new FileOutputStream(file);
//压缩流
ZipOutputStream toClient = new ZipOutputStream(outStream);
toClient.setEncoding("gbk");
zipFile(files, toClient);
toClient.close();
outStream.close();
this.downloadZip(file, response);
}
/**
* 压缩文件列表中的文件
* @param files
* @param outputStream
* @throws IOException
*/
public static void zipFile(List files, ZipOutputStream outputStream) throws IOException,ServletException
{
try
{
int size = files.size();
//压缩列表中的文件
for(int i = 0; i < size; i++)
{
File file = (File) files.get(i);
zipFile(file, outputStream);
}
}
catch(IOException e)
{
throw e;
}
}
/**
* 将文件写入到zip文件中
* @param inputFile
* @param outputstream
* @throws Exception
*/
public static void zipFile(File inputFile, ZipOutputStream outputstream) throws IOException,ServletException
{
try{
if(inputFile.exists())
{
if(inputFile.isFile())
{
FileInputStream inStream = new FileInputStream(inputFile);
BufferedInputStream bInStream = new BufferedInputStream(inStream);
ZipEntry entry = new ZipEntry(inputFile.getName());
outputstream.putNextEntry(entry);

final int MAX_BYTE = 10 * 1024 *1024;    //最大的流为10M
long streamTotal = 0;                      //接受流的容量
int streamNum = 0;                      //流需要分开的数量
int leaveByte = 0;                      //文件剩下的字符数
byte[] inOutbyte;                          //byte数组接受文件的数据

streamTotal = bInStream.available();                        //通过available方法取得流的最大字符数
streamNum = (int)Math.floor(streamTotal / MAX_BYTE);    //取得流文件需要分开的数量
leaveByte = (int)streamTotal % MAX_BYTE;                //分开文件之后,剩余的数量

if (streamNum > 0)
{
for(int j = 0; j < streamNum; ++j)
{
inOutbyte = new byte[MAX_BYTE];
//读入流,保存在byte数组
bInStream.read(inOutbyte, 0, MAX_BYTE);
outputstream.write(inOutbyte, 0, MAX_BYTE);  //写出流
}
}
//写出剩下的流数据
inOutbyte = new byte[leaveByte];
bInStream.read(inOutbyte, 0, leaveByte);
            outputstream.setEncoding("gbk");//解决中文文件名乱码
outputstream.write(inOutbyte);
outputstream.closeEntry();     //Closes the current ZIP entry and positions the stream for writing the next entry
bInStream.close();    //关闭
inStream.close();
}
}
else
{
throw new ServletException("文件不存在!");
}
}
catch(IOException e)
{
throw e;
}
}
/**
* 下载打包的文件
* @param file
* @param response
*/
public void downloadZip(File file,HttpServletResponse response) {
try {
// 以流的形式下载文件。
BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();

OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
toClient.write(buffer);
toClient.flush();
toClient.close();
file.delete();        //将生成的服务器端文件删除
}
catch (IOException ex) {
ex.printStackTrace();
}
}


单个文件的下载直接下载文件即可,使用java自带的FileOutputStream就能实现,可以从上面的批量下载中提取单个文件下载的方法。

  涉及到文件名称编码的问题,这里提供一个格式化中文字符串的方法。

public static String toUtf8String(String s){
StringBuffer sb = new StringBuffer();
for (int i = 0;i < s.length(); i++){
char c = s.charAt(i);
if (c >= 0 && c <= 255)
{
sb.append(c);
}
else{
byte[] b;
try
{
b = Character.toString(c).getBytes("utf-8");
}
catch (Exception ex) {
b = new byte[0];
}
for (int j = 0; j < b.length; j++) {
int k = b[j];
if (k < 0) k += 256;
sb.append("%" + Integer.toHexString(k).toUpperCase());
}
}
}
return sb.toString();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: