文件的上传与下载主要用到两种方法:

1、方法一:commons-fileupload.jar  commons-io.jar

apache的commons-fileupload实现文件上传,下载









【upload】

package com.handson.bbs.servlet;





import java.io.File;

import java.io.IOException;

import java.util.Date;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.handson.bbs.bo.UserBO;

import com.handson.bbs.model.User;

/** *//**

 * **********************************************

 * @description 文件上传

 *                 针对本项目,上传图片在uploadFile/Image

 *                         缓存目录 c:\\tmp\\ 目录下

 *                 照片上传后,后面代码处理及时更新用户照片。

 * @author Gavin.lee

 * @date 2009-6-13 21:35:47

 * @version 1.0

 ***********************************************

 */

public class UploadPhotoServlet extends HttpServlet{

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        this.doPost(request, response);

        

    }





    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {        

        String filepath = this.getServletContext().getRealPath("/uploadFile/Image/");    //容器相对路径

        

        File tmp = new File("c:\\tmp\\");

        if(! tmp.exists()) {

            tmp.mkdirs();

        }

        DiskFileItemFactory factory = new DiskFileItemFactory();    //创建磁盘工厂

        factory.setRepository(tmp);    //文件缓存路径

        factory.setSizeThreshold(10 * 1096 );

        ServletFileUpload sfu = new ServletFileUpload(factory);        //创建处理工具

        sfu.setSizeMax(10*1024*1024); //服务器端可以接收的最大文件大小,-1表示无上限

        String filename = null;

        try {

            List<FileItem> list = sfu.parseRequest(request);        //解析

            FileItem item= list.get(0);

            filename = item.getName();

            if(filename.equals("")) {

                request.getRequestDispatcher("/com/visualizePhoto.jsp").forward(request, response);

                return ;

            }            

            int pos = filename.lastIndexOf(".");                    //取图片文件格式

            if(pos > 0) {

                Date date = new Date();

                filename =filepath+'/'+ date.getTime()+filename.substring(pos);

            }

            item.write(new File(filename));    //写到磁盘

        } catch(Exception e) {

            e.printStackTrace();

        }

        

        // 只针对文件上传的话,后面代码不用看了,后面是针对及时更新用户信息(照片)

        HttpSession session = request.getSession();

        User user = (User)session.getAttribute("user");        

        int pos = filename.indexOf("uploadFile");    //设置图片相对路径

        if(pos > 0) {

            filename = filename.substring(pos,pos+10)+'/'+filename.substring(pos+11);

        }

        user.setPhoto(filename);

        

        UserBO userBo = UserBO.getInstance();

        if(userBo.updateUser(user)){

            session.setAttribute("user", user);

            request.getRequestDispatcher("/com/visualizePhoto.jsp").forward(request, response);

        }

    }





}





【download】

下载似乎就更简单了, package com.Gavin.tools.fileupload;





import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;





import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;





public class FileDownloadServlet extends HttpServlet {





    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException {

        String filename = request.getParameter("file_name");

        

        if (filename == null)

            filename = "";

        

        filename = filename.trim();





        InputStream inStream = null;

        String attchname = "";





        byte[] b = new byte[100];

        int len = 0;

        try {            

            attchname = getAttachName(filename);    //取得附件的名称

            filename = getRealName(request, filename);    //取得附件的全路径

            

            if (filename == null) {

                System.out.println("文件不存在,或者禁止下载");

                return;

            }

            attchname = toUtf8String(attchname);    //将文件转码 UTF-8

            inStream = new FileInputStream(filename);

            response.reset();    //必须reset,否则会出现文件不完整

            

            response.setContentType("application/x-msdownload");

            response.addHeader("Content-Disposition", "attachment; filename=\""    + attchname + "\"");

            

            //循环取出流中的数据 

            while ((len = inStream.read(b)) > 0) {

                response.getOutputStream().write(b, 0, len);

            }

            inStream.close();

            

        } catch (Exception e) {

            e.printStackTrace();

        }

    }





    //取得附件的名称

    public static String getAttachName(String filename) {

        if (filename == null)

            return "";

        filename = filename.trim();

        int pos = 0;

        

        pos = filename.lastIndexOf("\\");        

        if (pos > -1) {

            filename = filename.substring(pos + 1);

        }        

        

        pos = filename.lastIndexOf("/");        

        if (pos > -1) {

            filename = filename.substring(pos + 1);

        }

        

        pos = filename.lastIndexOf(File.separator);        

        if (pos > -1) {

            filename = filename.substring(pos + 1);

        }

        

        return filename;

    }





    //UTF8转码

    public static String toUtf8String(String string) {

        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < string.length(); i++) {

            char c = string.charAt(i);

            if (c >= 0 && c <= 255) {

                sb.append(c);

            } else {

                byte[] b;

                try {

                    b = Character.toString(c).getBytes("utf-8");

                } catch (Exception ex) {

                    System.out.println(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());

                }

            }

        }

        String s_utf8 = sb.toString();

        sb.delete(0, sb.length());

        sb.setLength(0);

        sb = null;

        return s_utf8;

    }





    //取得下载文件的真实全路径名称

    private String getRealName(HttpServletRequest request, String filename) {

        if (request == null || filename == null)

            return null;

        filename = filename.trim();

        if (filename.equals(""))

            return null;





        String filepath = request.getRealPath(filename);

        if (filepath == null)

            return null;

        File file = new File(filepath);

        if (!file.exists())

            return null;

        return filepath;

    }





    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException {        

        this.doPost(request, response);

    }





}

___________________________________________________________________________________________

___________________________________________________________________________________________

方法二 :jspsmartupload.jar

jspSmartUpload是由www.jspsmart.com网站开发的一个可免费使用的全功能的文件上传下载组件,适于嵌入执行上传下载操作的JSP文件中。该组件有以下几个特点: 



1、使用简单。在JSP文件中仅仅书写三五行java代码就可以搞定文件的上传或下载,方便。 



2、能全程控制上传。利用jspSmartUpload组件提供的对象及其操作方法,可以获得全部上传文件的信息(包括文件名,大小,类型,扩展名,文件数据等),方便存取。 



3、能对上传的文件在大小、类型等方面做出限制。如此可以滤掉不符合要求的文件。 



4、下载灵活。仅写两行代码,就能把Web服务器变成文件服务器。不管文件在Web服务器的目录下或在其它任何目录下,都可以利用jspSmartUpload进行下载。 



5、能将文件上传到数据库中,也能将数据库中的数据下载下来。这种功能针对的是MySQL数据库,因为不具有通用性,所以本文不准备举例介绍这种用法。 



  jspSmartUpload组件可以从www.jspsmart.com网站上自由下载,压缩包的名字是jspSmartUpload.zip。下载后,用WinZip或WinRAR将其解压到Tomcat的webapps目录下(本文以Tomcat服务器为例进行介绍)。解压后,将webapps/jspsmartupload目录下的子目录Web-inf名字改为全大写的WEB-INF,这样一改jspSmartUpload类才能使用。因为Tomcat对文件名大小写敏感,它要求Web应用程序相关的类所在目录为WEB-INF,且必须是大写。接着重新启动Tomcat,这样就可以在JSP文件中使用jspSmartUpload组件了。 



  注意,按上述方法安装后,只有webapps/jspsmartupload目录下的程序可以使用jspSmartUpload组件,如果想让Tomcat服务器的所有Web应用程序都能用它,必须做如下工作: 



1.进入命令行状态,将目录切换到Tomcat的webapps/jspsmartupload/WEB-INF目录下。 



2.运行JAR打包命令:jar cvf jspSmartUpload.jar com 



(也可以打开资源管理器,切换到当前目录,用WinZip将com目录下的所有文件压缩成jspSmartUpload.zip,然后将jspSmartUpload.zip换名为jspSmartUpload.jar文件即可。) 



3.将jspSmartUpload.jar拷贝到Tomcat的shared/lib目录下。 



二、相关类说明篇 



㈠ File类 



  这个类包装了一个上传文件的所有信息。通过它,可以得到上传文件的文件名、文件大小、扩展名、文件数据等信息。 



  File类主要提供以下方法: 



1、saveAs作用:将文件换名另存。 



原型: 



public void saveAs(java.lang.String destFilePathName) 



或 



public void saveAs(java.lang.String destFilePathName, int optionSaveAs) 



其中,destFilePathName是另存的文件名,optionSaveAs是另存的选项,该选项有三个值,分别是SAVEAS_PHYSICAL,SAVEAS_VIRTUAL,SAVEAS_AUTO。SAVEAS_PHYSICAL表明以操作系统的根目录为文件根目录另存文件,SAVEAS_VIRTUAL表明以Web应用程序的根目录为文件根目录另存文件,SAVEAS_AUTO则表示让组件决定,当Web应用程序的根目录存在另存文件的目录时,它会选择SAVEAS_VIRTUAL,否则会选择SAVEAS_PHYSICAL。 



例如,saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)执行后若Web服务器安装在C盘,则另存的文件名实际是c:\upload\sample.zip。而saveAs("/upload/sample.zip",SAVEAS_VIRTUAL)执行后若Web应用程序的根目录是webapps/jspsmartupload,则另存的文件名实际是webapps/jspsmartupload/upload/sample.zip。saveAs("/upload/sample.zip",SAVEAS_AUTO)执行时若Web应用程序根目录下存在upload目录,则其效果同saveAs("/upload/sample.zip",SAVEAS_VIRTUAL),否则同saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)。 



建议:对于Web程序的开发来说,最好使用SAVEAS_VIRTUAL,以便移植。 



2、isMissing 



作用:这个方法用于判断用户是否选择了文件,也即对应的表单项是否有值。选择了文件时,它返回false。未选文件时,它返回true。 



原型:public boolean isMissing() 



3、getFieldName 



作用:取HTML表单中对应于此上传文件的表单项的名字。 



原型:public String getFieldName() 



4、getFileName 



作用:取文件名(不含目录信息) 



原型:public String getFileName() 



5、getFilePathName 



作用:取文件全名(带目录) 



原型:public String getFilePathName 



6、getFileExt 



作用:取文件扩展名(后缀) 



原型:public String getFileExt() 



7、getSize 



作用:取文件长度(以字节计) 



原型:public int getSize() 



8、getBinaryData 



作用:取文件数据中指定位移处的一个字节,用于检测文件等处理。 



原型:public byte getBinaryData(int index)。其中,index表示位移,其值在0到getSize()-1之间。 



㈡ Files类 



  这个类表示所有上传文件的集合,通过它可以得到上传文件的数目、大小等信息。有以下方法: 



1、getCount 



作用:取得上传文件的数目。 



原型:public int getCount() 



2、getFile 



作用:取得指定位移处的文件对象File(这是com.jspsmart.upload.File,不是java.io.File,注意区分)。 



原型:public File getFile(int index)。其中,index为指定位移,其值在0到getCount()-1之间。 



3、getSize 



作用:取得上传文件的总长度,可用于限制一次性上传的数据量大小。 



原型:public long getSize() 



4、getCollection 



作用:将所有上传文件对象以Collection的形式返回,以便其它应用程序引用,浏览上传文件信息。 



原型:public Collection getCollection() 



5、getEnumeration 



作用:将所有上传文件对象以Enumeration(枚举)的形式返回,以便其它应用程序浏览上传文件信息。 



原型:public Enumeration getEnumeration() 



㈢ Request类 



  这个类的功能等同于JSP内置的对象request。只所以提供这个类,是因为对于文件上传表单,通过request对象无法获得表单项的值,必须通过jspSmartUpload组件提供的Request对象来获取。该类提供如下方法: 



1、getParameter 



作用:获取指定参数之值。当参数不存在时,返回值为null。 



原型:public String getParameter(String name)。其中,name为参数的名字。 



2、getParameterValues 



作用:当一个参数可以有多个值时,用此方法来取其值。它返回的是一个字符串数组。当参数不存在时,返回值为null。 



原型:public String[] getParameterValues(String name)。其中,name为参数的名字。 



3、getParameterNames 



作用:取得Request对象中所有参数的名字,用于遍历所有参数。它返回的是一个枚举型的对象。 



原型:public Enumeration getParameterNames() 



㈣ SmartUpload类这个类完成上传下载工作。 



A.上传与下载共用的方法: 



只有一个:initialize。 



作用:执行上传下载的初始化工作,必须第一个执行。 



原型:有多个,主要使用下面这个: 



public final void initialize(javax.servlet.jsp.PageContext pageContext) 



其中,pageContext为JSP页面内置对象(页面上下文)。 



B.上传文件使用的方法: 



1、upload 



作用:上传文件数据。对于上传操作,第一步执行initialize方法,第二步就要执行这个方法。



原型:public void upload() 



2、save 



作用:将全部上传文件保存到指定目录下,并返回保存的文件个数。 



原型:public int save(String destPathName) 



和public int save(String destPathName,int option) 



其中,destPathName为文件保存目录,option为保存选项,它有三个值,分别是SAVE_PHYSICAL,SAVE_VIRTUAL和SAVE_AUTO。(同File类的saveAs方法的选项之值类似)SAVE_PHYSICAL指示组件将文件保存到以操作系统根目录为文件根目录的目录下,SAVE_VIRTUAL指示组件将文件保存到以Web应用程序根目录为文件根目录的目录下,而SAVE_AUTO则表示由组件自动选择。 



注:save(destPathName)作用等同于save(destPathName,SAVE_AUTO)。 



3、getSize 



作用:取上传文件数据的总长度 



原型:public int getSize() 



4、getFiles 



作用:取全部上传文件,以Files对象形式返回,可以利用Files类的操作方法来获得上传文件的数目等信息。 



原型:public Files getFiles() 



5、getRequest 



作用:取得Request对象,以便由此对象获得上传表单参数之值。 



原型:public Request getRequest() 



6、setAllowedFilesList 



作用:设定允许上传带有指定扩展名的文件,当上传过程中有文件名不允许时,组件将抛出异常。 



原型:public void setAllowedFilesList(String allowedFilesList) 



其中,allowedFilesList为允许上传的文件扩展名列表,各个扩展名之间以逗号分隔。如果想允许上传那些没有扩展名的文件,可以用两个逗号表示。例如:setAllowedFilesList("doc,txt,,")将允许上传带doc和txt扩展名的文件以及没有扩展名的文件。 



7、setDeniedFilesList 



作用:用于限制上传那些带有指定扩展名的文件。若有文件扩展名被限制,则上传时组件将抛出异常。 



原型:public void setDeniedFilesList(String deniedFilesList) 



其中,deniedFilesList为禁止上传的文件扩展名列表,各个扩展名之间以逗号分隔。如果想禁止上传那些没有扩展名的文件,可以用两个逗号来表示。例如:setDeniedFilesList("exe,bat,,")将禁止上传带exe和bat扩展名的文件以及没有扩展名的文件。 



8、setMaxFileSize 



作用:设定每个文件允许上传的最大长度。 



原型:public void setMaxFileSize(long maxFileSize) 



其中,maxFileSize为为每个文件允许上传的最大长度,当文件超出此长度时,将不被上传。 



9、setTotalMaxFileSize 



作用:设定允许上传的文件的总长度,用于限制一次性上传的数据量大小。 



原型:public void setTotalMaxFileSize(long totalMaxFileSize) 



其中,totalMaxFileSize为允许上传的文件的总长度。 



C.下载文件常用的方法 



1、setContentDisposition 



作用:将数据追加到MIME文件头的CONTENT-DISPOSITION域。jspSmartUpload组件会在返回下载的信息时自动填写MIME文件头的CONTENT-DISPOSITION域,如果用户需要添加额外信息,请用此方法。 



原型:public void setContentDisposition(String contentDisposition) 



其中,contentDisposition为要添加的数据。如果contentDisposition为null,则组件将自动添加"attachment;",以表明将下载的文件作为附件,结果是IE浏览器将会提示另存文件,而不是自动打开这个文件(IE浏览器一般根据下载的文件扩展名决定执行什么操作,扩展名为doc的将用Word程序打开,扩展名为pdf的将用acrobat程序打开,等等)。 



2、downloadFile 



作用:下载文件。 



原型:共有以下三个原型可用,第一个最常用,后两个用于特殊情况下的文件下载(如更改内容类型,更改另存的文件名)。 



① public void downloadFile(String sourceFilePathName) 



其中,sourceFilePathName为要下载的文件名(带目录的文件全名) 



② public void downloadFile(String sourceFilePathName,String contentType) 



其中,sourceFilePathName为要下载的文件名(带目录的文件全名),contentType为内容类型(MIME格式的文件类型信息,可被浏览器识别)。 



③ public void downloadFile(String sourceFilePathName,String contentType,String destFileName) 



其中,sourceFilePathName为要下载的文件名(带目录的文件全名),contentType为内容类型(MIME格式的文件类型信息,可被浏览器识别),destFileName为下载后默认的另存文件名。 



三、文件上传篇 



㈠ 表单要求 



对于上传文件的FORM表单,有两个要求: 



1、METHOD应用POST,即METHOD="POST"。 



2、增加属性:ENCTYPE="multipart/form-data" 



下面是一个用于上传文件的FORM表单的例子:

<FORM METHOD="POST" ENCTYPE="multipart/form-data"
ACTION="/jspSmartUpload/upload.jsp">
<INPUT TYPE="FILE" NAME="MYFILE">
<INPUT TYPE="SUBMIT">
</FORM>

㈡ 上传的例子 



1、上传页面upload.html 



本页面提供表单,让用户选择要上传的文件,点击"上传"按钮执行上传操作。 



页面源码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>文件上传</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head> <body>
<p>&nbsp;</p>
<p align="center">上传文件选择</p>
<FORM METHOD="POST" ACTION="jsp/do_upload.jsp"
ENCTYPE="multipart/form-data">
<input type="hidden" name="TEST" value="good">
<table width="75%" border="1" align="center">
<tr>
<td><div align="center">1、
<input type="FILE" name="FILE1" size="30">
</div></td>
</tr>
<tr>
<td><div align="center">2、
<input type="FILE" name="FILE2" size="30">
</div></td>
</tr>
<tr>
<td><div align="center">3、
<input type="FILE" name="FILE3" size="30">
</div></td>
</tr>
<tr>
<td><div align="center">4、
<input type="FILE" name="FILE4" size="30">
</div></td>
</tr>
<tr>
<td><div align="center">
<input type="submit" name="Submit" value="上传它!">
</div></td>
</tr>
</table>
</FORM>
</body>
</html>

2、上传处理页面do_upload.jsp 



本页面执行文件上传操作。页面源码中详细介绍了上传方法的用法,在此不赘述了。 



页面源码如下:

<%@ page contentType="text/html; charset=gb2312" language="java"
import="java.util.*,com.jspsmart.upload.*" errorPage="" %>
<html>
<head>
<title>文件上传处理页面</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head> <body>
<%
// 新建一个SmartUpload对象
SmartUpload su = new SmartUpload();
// 上传初始化
su.initialize(pageContext);
// 设定上传限制
// 1.限制每个上传文件的最大长度。
// su.setMaxFileSize(10000);
// 2.限制总上传数据的长度。
// su.setTotalMaxFileSize(20000);
// 3.设定允许上传的文件(通过扩展名限制),仅允许doc,txt文件。
// su.setAllowedFilesList("doc,txt");
// 4.设定禁止上传的文件(通过扩展名限制),禁止上传带有exe,bat,
jsp,htm,html扩展名的文件和没有扩展名的文件。
// su.setDeniedFilesList("exe,bat,jsp,htm,html,,");
// 上传文件
su.upload();
// 将上传文件全部保存到指定目录
int count = su.save("/upload");
out.PRintln(count+"个文件上传成功!<br>"); // 利用Request对象获取参数之值
out.println("TEST="+su.getRequest().getParameter("TEST")
+"<BR><BR>"); // 逐一提取上传文件信息,同时可保存文件。
for (int i=0;i<su.getFiles().getCount();i++)
{
com.jspsmart.upload.File file = su.getFiles().getFile(i); // 若文件不存在则继续
if (file.isMissing()) continue; // 显示当前文件信息
out.println("<TABLE BORDER=1>");
out.println("<TR><TD>表单项名(FieldName)</TD><TD>"
+ file.getFieldName() + "</TD></TR>");
out.println("<TR><TD>文件长度(Size)</TD><TD>" +
file.getSize() + "</TD></TR>");
out.println("<TR><TD>文件名(FileName)</TD><TD>"
+ file.getFileName() + "</TD></TR>");
out.println("<TR><TD>文件扩展名(FileExt)</TD><TD>"
+ file.getFileExt() + "</TD></TR>");
out.println("<TR><TD>文件全名(FilePathName)</TD><TD>"
+ file.getFilePathName() + "</TD></TR>");
out.println("</TABLE><BR>"); // 将文件另存
// file.saveAs("/upload/" + myFile.getFileName());
// 另存到以WEB应用程序的根目录为文件根目录的目录下
// file.saveAs("/upload/" + myFile.getFileName(),
su.SAVE_VIRTUAL);
// 另存到操作系统的根目录为文件根目录的目录下
// file.saveAs("c:\\temp\\" + myFile.getFileName(),
su.SAVE_PHYSICAL); }
%>
</body>
</html>

四、文件下载篇 



1、下载链接页面download.html 



页面源码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>下载</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<a href="jsp/do_download.jsp">点击下载</a>
</body>
</html>

2、下载处理页面do_download.jsp do_download.jsp展示了如何利用jspSmartUpload组件来下载文件,从下面的源码中就可以看到,下载何其简单。 



源码如下:

<%@ page contentType="text/html;charset=gb2312"
import="com.jspsmart.upload.*" %><%
// 新建一个SmartUpload对象
SmartUpload su = new SmartUpload();
// 初始化
su.initialize(pageContext);
// 设定contentDisposition为null以禁止浏览器自动打开文件,
//保证点击链接后是下载文件。若不设定,则下载的文件扩展名为
//doc时,浏览器将自动用word打开它。扩展名为pdf时,
//浏览器将用acrobat打开。
su.setContentDisposition(null);
// 下载文件
su.downloadFile("/upload/如何赚取我的第一桶金.doc");
%>

注意,执行下载的页面,在Java脚本范围外(即<% ... %>之外),不要包含HTML代码、空格、回车或换行等字符,有的话将不能正确下载。不信的话,可以在上述源码中%><%之间加入一个换行符,再下载一下,保证出错。因为它影响了返回给浏览器的数据流,导致解析出错。 



3、如何下载中文文件 



jspSmartUpload虽然能下载文件,但对中文支持不足。若下载的文件名中有汉字,则浏览器在提示另存的文件名时,显示的是一堆乱码,很扫人兴。上面的例子就是这样。(这个问题也是众多下载组件所存在的问题,很少有人解决,搜索不到相关资料,可叹!) 



为了给jspSmartUpload组件增加下载中文文件的支持,我对该组件进行了研究,发现对返回给浏览器的另存文件名进行UTF-8编码后,浏览器便能正确显示中文名字了。这是一个令人高兴的发现。于是我对jspSmartUpload组件的SmartUpload类做了升级处理,增加了toUtf8String这个方法,改动部分源码如下:

public void downloadFile(String s, String s1, String s2, int i)
throws ServletException, IOException, SmartUploadException
{
if(s == null)
throw new IllegalArgumentException("File '" + s +
"' not found (1040).");
if(s.equals(""))
throw new IllegalArgumentException("File '" + s +
"' not found (1040).");
if(!isVirtual(s) && m_denyPhysicalPath)
throw new SecurityException("Physical path is
denied (1035).");
if(isVirtual(s))
s = m_application.getRealPath(s);
java.io.File file = new java.io.File(s);
FileInputStream fileinputstream = new FileInputStream(file);
long l = file.length();
boolean flag = false;
int k = 0;
byte abyte0[] = new byte[i];
if(s1 == null)
m_response.setContentType("application/x-msdownload");
else
if(s1.length() == 0)
m_response.setContentType("application/x-msdownload");
else
m_response.setContentType(s1);
m_response.setContentLength((int)l);
m_contentDisposition = m_contentDisposition != null ?
m_contentDisposition : "attachment;";
if(s2 == null)
m_response.setHeader("Content-Disposition",
m_contentDisposition + " filename=" +
toUtf8String(getFileName(s)));
else
if(s2.length() == 0)
m_response.setHeader("Content-Disposition",
m_contentDisposition);
else
m_response.setHeader("Content-Disposition",
m_contentDisposition + " filename=" + toUtf8String(s2));
while((long)k < l)
{
int j = fileinputstream.read(abyte0, 0, i);
k += j;
m_response.getOutputStream().write(abyte0, 0, j);
}
fileinputstream.close();
} /**
* 将文件名中的汉字转为UTF8编码的串,以便下载时能正确显示另存的文件名.
* 纵横软件制作中心雨亦奇2003.08.01
* @param s 原文件名
* @return 重新编码后的文件名
*/
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) {
System.out.println(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();
}

注意源码中粗体部分,原jspSmartUpload组件对返回的文件未作任何处理,现在做了编码的转换工作,将文件名转换为UTF-8形式的编码形式。UTF-8编码对英文未作任何处理,对中文则需要转换为%XX的形式。toUtf8String方法中,直接利用Java语言提供的编码转换方法获得汉字字符的UTF-8编码,之后将其转换为%XX的形式。 



将源码编译后打包成jspSmartUpload.jar,拷贝到Tomcat的shared/lib目录下(可为所有WEB应用程序所共享),然后重启Tomcat服务器就可以正常下载含有中文名字的文件了。另,toUtf8String方法也可用于转换含有中文的超级链接,以保证链接的有效,因为有的WEB服务器不支持中文链接。

Java中文件的上传与下载的更多相关文章

  1. JavaWeb中文件的上传和下载

    JavaWeb中文件的上传和下载 转自: JavaWeb学习总结(五十)——文件上传和下载 - 孤傲苍狼 - 博客园https://www.cnblogs.com/xdp-gacl/p/4200090 ...

  2. iOS开发中文件的上传和下载功能的基本实现-备用

    感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传 ...

  3. java客户端文件的上传和下载

    java客户端文件的上传和下载 //上传 public JTable upload(String id){ JTable table=new JTable(); System.out.println( ...

  4. java实现文件的上传和下载

    1. servlet 如何实现文件的上传和下载? 1.1上传文件 参考自:http://blog.csdn.net/hzc543806053/article/details/7524491 通过前台选 ...

  5. 009 spring boot中文件的上传与下载

    一:任务 1.任务 文件的上传 文件的下载 二:文件的上传 1.新建一个对象 FileInfo.java package com.cao.dto; public class FileInfo { pr ...

  6. java实现文件的上传与下载

    (一)文件的上传:在这一部分,我要将execl文件的内容上传到数据库中,完成这一功能.需要分为两步: 1:将文件上传到tomcat下 文件格式如下: 2:读取execl表中的内容到数据库中 首先:下载 ...

  7. Java中资料的上传与下载

    1.导架包 <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons ...

  8. Struts中文件的上传与下载

    前面学到的用组件去上传 前台: 1.post表单提交 2.表单类型 multipart/form-data 3.intput type=file 后台: Apach提供的FileUpload组件 核心 ...

  9. JSP中文件的上传于下载演示样例

    一.文件上传的原理     1.文件上传的前提:         a.form表单的method必须是post         b.form表单的enctype必须是multipart/form-da ...

随机推荐

  1. [Debug] Chrome Devtools: Elements - Console Integration

    The Element Inspector in Chrome DevTools offers powerful integration with the console - learn how to ...

  2. hibernate---java.lang.UnsupportedOperationException: The user must supply a JDBC connection

        在配置hibernate时.运行代码时一直抛错: Exception in thread "main" java.lang.UnsupportedOperationExce ...

  3. php二维数组中的查找(善于利用基础函数)

    php二维数组中的查找(善于利用基础函数) 一.总结 真没必要完整的写函数,善于借用 1.array_search()是在以为数组中来找,现在我们要在二维数组数组中来,肯定要借用这个 2.!==fal ...

  4. java I/O库的设计模式

    在java语言 I/O库的设计中,使用了两个结构模式,即装饰模式和适配器模式.      在任何一种计算机语言中,输入/输出都是一个很重要的部分.与一般的计算机语言相比,java将输入/输出的功能和使 ...

  5. Tampermonkey版Vimium

    Tampermonkey版Vimium https://zhuanlan.zhihu.com/p/27222664

  6. SqlBulkCopy 帮助类

    using System;using System.Collections.Generic;using System.Configuration;using System.Data;using Sys ...

  7. DOM中Event 对象如何使用

    DOM中Event 对象如何使用 一.总结 一句话总结: 1.将event作为参数传递进来,然后就可以调用event对象的各种属性和方法了. <body onmousedown="wh ...

  8. HTML5移动开发实战必备知识——本地存储(1)

    本地缓存是HTML5出现的新技术,这个技术的出现使得移动web的开发成为了可能.我们都知道.要想打造一个高性能的移动应用,速度是关键.而在HTML5之前.仅仅有cookie可以存储数据,大小仅仅有4k ...

  9. DDoS ATTACK PROCESSING APPARATUS AND METHOD IN OPENFLOW SWITCH

    An OpenFlow switch in an OpenFlow environment includes an attack determination module to collect sta ...

  10. Android网络应用之Socket(一)

    socket编程是网络通信的一个基础应用.不管是手机端还是PC端都须要socket技术来建立网络通信. 在本章小编主要从下面几个方面来介绍socket的相关知识: 各自是"什么是socket ...