`

显示work,excel 文档

    博客分类:
  • java
阅读更多
这些说起来是入门级的东西,但没有几个人真的知道.
要输出一个excel,内容当然是你自己的逻辑,但MIME要非常熟悉.
<%@page contentType="application/msexcel"%>
<%
response.setHeader("Content-disposition", "inline;filename=test.xls");
%>
inline是内联方式,也就是在当前文档中打开.如果是IE就是在IE窗口中打开这个文档,如果是email就是内嵌在邮件中而不是作为附件.

如果要下载,则描述符为:attachment,邮件中就是附件,IE中就是下载



TestFileDownload.JSP页面的例子:

<%
// 得到文件名字和路径
String filename = ”MengxianhuiDocTest.doc”;
String filepath = ”D:\\”;

// 设置响应头和下载保存的文件名
response.setContentType(”APPLICATION/OCTET-STREAM”)&#59;
response.setHeader(”Content-Disposition”,
”attachment&#59; filename=\”” + filename + ”\””)&#59;

// 打开指定文件的流信息
java.io.FileInputStream fileInputStream =
new java.io.FileInputStream(filepath + filename)&#59;

// 写出流信息
int i&#59;
while ((i=fileInputStream.read()) != -1) {
out.write(i)&#59;
}
fileInputStream.close()&#59;
out.close()&#59;
%>;

值得注意的是:在你要下载的文件内容里,除了文件的内容之外,不应该再附加有其它任何的字符,包括空格和回车换行符。我们有时在编写代码的时候,为了使代码清晰可读,往往会添加一些空格、制表符或者回车换行符,这样虽然看起来比较清晰,但有时可能会得不到正确的结果。比如:
<%@ page import=”java.io.*”
%>; <jsp:useBean id=”MyBeanFromMengxianhui” scope=”page”
class=”com.Mengxianhui.DownloadBean” />;
应该写成这样:
<%@ page import=”java.io.*”
%>;<jsp:useBean id=”MyBeanFromMengxianhui” scope=”page”
class=”com.Mengxianhui.DownloadBean” />;


--------------------------------------------------------------------------------
eclipse 回复于:2002-10-18 12:13:21

请注意:APPLICATION/OCTET-STREAM是设置下载类型

要改成你实际的类型,如excel要写成:application/vnd.ms-excel



--------------------------------------------------------------------------------
eclipse 回复于:2002-10-18 12:17:39

如果不用jspsmart,你就需要了解浏览器端的编码方式,在传到服务器端时你才能解码。也才可以得到上传文件的相关信息。看下面的代码。
package mshtang.fileUpload&#59;
import java.io.*&#59;
/**一个存放文件信息的类,包括文件的名称(String),
**字段名(String), Content-Type(String)和内容(byte[])
**还提供了一个直接将文件内容保存到一个文件的函数 void saveTo(File f)
**可以调用 类{@link ContentFactory}中的适当方法,生成该类的实例。
** @see ContentFactory
** @see ContentFactory#getFileParameter
** @see ContentFactory#getFileParameterValues
**/

public class FileHolder
{
    String contentType&#59;
    byte[] buffer&#59;
    String fileName&#59;
    String parameterName&#59;

    FileHolder(byte[] buffer, String contentType, String fileName, String parameterName)
    {
        this.buffer = buffer&#59;
        this.contentType = contentType&#59;
        this.fileName = fileName&#59;
        this.parameterName = parameterName&#59;
    }
    /**把文件的内容存到指定的文件中,
    **<b>;这个方法不会检查这个文件是否可写、是否已经存在。</b>;
    **@param file  目的文件
    **@throws 在 I/O 操作中被抛出的 IOException
    **/
    public void saveTo(File file) throws IOException
    {
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))&#59;
        out.write(buffer)&#59;
        out.close()&#59;
    }

    /**把文件的内容存到指定的文件中,
    **<b>;这个方法不会检查这个文件是否可写、是否已经存在。</b>;
    **@param name 目的文件名
    **@throws 在 I/O 操作中被抛出的 IOException
    **/
    public void saveTo(String name) throws IOException
    {
        saveTo(new File(name))&#59;
    }

   /**
    **返回一个文件内容的字节数组
    **@return 一个代表文件内容的字节数组
   **/
    public byte[] getBytes()
    {
        return buffer&#59;
    }

   /**
    **返回该文件在文件上载前在客户端的名称
    **@return 该文件在文件上载前在客户端的名称
   **/
    public String getFileName()
    {
        return fileName&#59;
    }

   /**
    **返回该文件的 Content-Type
    **@return 该文件的 Content-Type
   **/
    public String getContentType()
    {
        return contentType&#59;
    }

   /**
    **返回上载该文件时,Html 页面窗体中 file 控件的 name 属性
    **@return 返回上载该文件时,Html 页面窗体中 file 控件的 name 属性
   **/
    public String getParameterName()
    {
        return parameterName&#59;
    }
}


package mshtang.fileUpload&#59;
import java.io.*&#59;
import javax.servlet.*&#59;
import javax.servlet.http.*&#59;
import java.util.*&#59;

/**存放报文内容的类,提供类似于 ServletRequest 中的部分 get 方法
*你必须在 html 页面的窗体(form)中指定 enctype=&quot;multipart/form-data&quot;。
*才可以正确的使用这个类。
**/
public class ContentFactory
{
    private Hashtable values&#59;        //存放name=value,其中value存放在另一个类中
    private Hashtable files&#59;         //存放文件内容的。
    private ContentFactory(Hashtable values, Hashtable files)
    {
        this.values=values&#59;
        this.files=files&#59;
    }
    public String getParameter(String name)
    {
        Vector v = (Vector)values.get(name)&#59;
        if( v != null)
        {
          return (String)v.elementAt(0)&#59;
        }
        return null&#59;
    }
    public Enumeration getParameterNames()
    {
        return values.keys()&#59;
    }
    public String[] getParameterValues(String name)
    {
        Vector v = (Vector)values.get(name)&#59;
        if(v != null)
        {
          String[] result = new String[v.size()]&#59;
          v.toArray(result)&#59;
          return result&#59;
        }
        return new String[0]&#59;
    }

   /**
     *返回一个 FileHolder 实例,该实例包含了通过字段名为name的file控件上载的文件信息,
     *如果不存在这个字段或者提交页面时,没有选择上载的文件,则返回 null。
     * <p>;如果 Html 页面中存在不止一个字段名为name的file控件,
     * 返回值等于{@link #getFileParameterValues}中的第一个元素。
     *
     * @param name:一个<code>;String</code>;,对应于Html页面窗体中file控件
     *的name 属性。
     *
     * @return返回:一个 FileHolder 实例,该实例包含了通过字段名为 name 的 file 控件上载的文件信息,
     *如果不存在这个字段或者提交页面是,没有选择上载的文件,则返回 null。
     *
     * @see         #getFileParameterValues
     *
     */
    public FileHolder getFileParameter(String name)
    {
        Vector v = (Vector)files.get(name)&#59;
        if(v != null)
        {
          return (FileHolder)v.elementAt(0)&#59;
        }
        return null&#59;
    }
    /**
     * 返回一个 由 String 对象构成的 Enumeration ,包含了 Html 页面
     *窗体中所有 file 控件的 name 属性。
     *如果窗体中没有 file 控件,则返回一个空的 Enumeration
     * @return             返回一个 由 String 对象构成的 Enumeration ,包含了 Html 页面
     *窗体中所有 file 控件的 name 属性。
     *如果窗体中没有 file 控件,则返回一个空的 Enumeration
     */
    public Enumeration getFileParameterNames()
    {
        return files.keys()&#59;
    }
   /**
     *返回一个 FileHolder 数组,该数组包含了所有通过字段名为 name 的 file 控件上载的文件信息,
     *如果不存在这个字段或者提交页面时,没有选择任何上载的文件,则返回一个 零元素的数组(不是 null )。
     * @param name     一个 <code>;String</code>; ,对应于 Html 页面窗体中 file 控件
     *的name 属性。
     *
     * @return        返回一个 FileHolder 数组,该数组包含了所有通过字段名为 name 的 file 控件上载的文件信息,
     *如果不存在这个字段或者提交页面时,没有选择任何上载的文件,则返回一个 零元素的数组(不是 null )。
     *
     * @see         #getFileParameter
     */
    public FileHolder[] getFileParameterValues(String name)
    {
        Vector v=(Vector)files.get(name)&#59;
        if(v!=null)
        {
            FileHolder[] result=new FileHolder[v.size()]&#59;
            v.toArray(result)&#59;
            return result&#59;
        }
        return new FileHolder[0]&#59;
    }
    //------------->;Factory 部分
    /**
    **返回根据当前请求生成的一个 ContentFactory 实例
    **@param request 提交的请求
    **@return 返回根据当前请求生成的一个 ContentFactory 实例,如果 request
    数据包的内容不是以 mutilpart/form-data 型编码,则返回 null。
    **@throws ContentFactoryException 当提交的数据和文件太大时抛出,
    **根据 Content-Length 判断,默认的许可值为 1024* 1024。
    **/
    public static ContentFactory getContentFactory(HttpServletRequest request) throws ContentFactoryException,IOException
    {
        // default maxLength is 1MB.
        return getContentFactory(request, 1024*1024)&#59;
    }
        /**
    **返回根据当前请求生成的一个 ContentFactory 实例
    **@param request 提交的请求
    **@param maxLength 数据包的最大长度,默认为1024*1024
    **@return 返回根据当前请求生成的一个 ContentFactory 实例,如果 request
    数据包的内容不是以 mutilpart/form-data 型编码,则返回 null。
    **@throws ContentFactoryException 当提交的数据和文件太大时抛出,
    **根据 Content-Length 判断,默认的许可值为 1024* 1024。
    **/
    public static ContentFactory getContentFactory(HttpServletRequest request, int maxLength) throws ContentFactoryException, IOException
    {
      Hashtable values = new Hashtable()&#59;
      Hashtable files = new Hashtable()&#59;
      String contentType = request.getContentType()&#59;
      int contentLength = request.getContentLength()&#59;
      if (contentLength >; maxLength)
      {
        ContentFactoryException e=new ContentFactoryException(&quot;上传数据太多,请不要选择太大的文件&quot;)&#59;
        throw e&#59;
      }
      if(contentType == null || !contentType.startsWith(&quot;multipart/form-data&quot;))
      {
        return null&#59;
      }
//get out the boudary from content-type
      int start = contentType.indexOf(&quot;boundary=&quot;)&#59;
//这里应该
      int boundaryLen = new String(&quot;boundary=&quot;).length()&#59;
      String boundary = contentType.substring(start + boundaryLen)&#59;
      boundary = &quot;--&quot; + boundary&#59;
//用字节表示,以免 String  和 byte 数组的长度不一致
      boundaryLen = bytesLen(boundary)&#59;
//把request 中的数据读入一个byte数组
      byte buffer[] = new byte[contentLength]&#59;
      int once = 0&#59;
      int total = 0&#59;
      DataInputStream in = new DataInputStream(request.getInputStream())&#59;
      while((total < contentLength) &amp;&amp; (once >;= 0))
      {
        once = in.read(buffer, total, contentLength)&#59;
        total += once&#59;
      }
//对buffer中的数据进行拆分
      int pos1 = 0&#59;                  //pos1 记录 在buffer 中下一个 boundary 的位置
//pos0,pos1 用于 subBytes 的两个参数
      int pos0 = byteIndexOf(buffer, boundary, 0)&#59;//pos0 记录 boundary 的第一个字节在buffer 中的位置
      do
      {
        pos0 += boundaryLen&#59;                                 //记录boundary后面第一个字节的下标
        pos1 = byteIndexOf(buffer, boundary, pos0)&#59;
        if(pos1==-1)
        {
          break&#59;
        }//
        pos0 += 2&#59;//考虑到boundary后面的 \r\n
        parse(subBytes(buffer, pos0, pos1-2), values, files)&#59;      //考虑到boundary后面的\r\n
        pos0=pos1&#59;
      }while(true)&#59;
      return new ContentFactory(values,files)&#59;
    }

private static void parse(byte[] buffer, Hashtable values, Hashtable files)
    {
            /* this is a smiple to parse
            [boundary]
            Content-Disposition: form-data&#59; name=&quot;file3&quot;&#59; filename=&quot;C:\Autoexec.bat&quot;
            Content-Type: application/octet-stream

            @echo off
            prompt $d $t [ $p ]$_$$

            [boundary]
            Content-Disposition: form-data&#59; name=&quot;Submit&quot;

            Submit
            [boundary]
            */
        String[] tokens={&quot;name=\&quot;&quot;,&quot;\&quot;&#59; filename=\&quot;&quot;, &quot;\&quot;\r\n&quot;,&quot;Content-Type: &quot;,&quot;\r\n\r\n&quot;}&#59;
           //                          0           1                               2          3                         4
        int[] position=new int[tokens.length]&#59;

        for (int i=0&#59;i<tokens.length &#59;i++ )
        {
            position=byteIndexOf(buffer,tokens,0)&#59;
        }
        if (position[1]>;0 &amp;&amp; position[1]<position[2])
        {
            //包含tokens 中的第二个元素,说明是个文件数据段
            //1.得到字段名
            String name =subBytesString(buffer,position[0]+bytesLen(tokens[0]),position[1])&#59;
            //2.得到文件名
            String file= subBytesString(buffer,position[1]+bytesLen(tokens[1]),position[2])&#59;
            if (file.equals(&quot;&quot;)) return&#59;
            file=new File(file).getName()&#59;     //this is the way to get the name from a path string
            //3.得到 Content-Type
            String contentType=subBytesString(buffer,position[3]+bytesLen(tokens[3]),position[4])&#59;
           //4.得到文件内容
            byte[] b=subBytes(buffer,position[4]+bytesLen(tokens[4]),buffer.length)&#59;
            FileHolder f=new FileHolder(b,contentType,file,name)&#59;
            Vector v=(Vector)files.get(name)&#59;
            if (v==null)
            {
                v=new Vector()&#59;
            }
            if (!v.contains(f))
            {
                v.add(f)&#59;
            }
            files.put(name,v)&#59;
            //同时将 name 属性和 file 属性作为普通字段,存入values&#59;
            v=(Vector)values.get(name)&#59;
            if (v==null)
            {
                v=new Vector()&#59;
            }
            if (!v.contains(file))
            {
                v.add(file)&#59;
            }
            values.put(name,v)&#59;
        }else
        {
//            String[] tokens={&quot;name=\&quot;&quot;,&quot;\&quot;&#59; filename=\&quot;&quot;, &quot;\&quot;\r\n&quot;,&quot;Content-Type: &quot;,&quot;\r\n\r\n&quot;}
//             index                      0           1                               2          3                         4
            //不包含tokens 中的第二个元素,说明是个 name/value 型的数据段
            //所以没有tokens[1]和 tokens[3]
            //name 在 tokens[0] 和 tokens[2] 之间
            //value 在 tokens[4]之后
            //1.得到name
            String name =subBytesString(buffer,position[0]+bytesLen(tokens[0]),position[2])&#59;
            String value= subBytesString(buffer,position[4]+bytesLen(tokens[4]),buffer.length)&#59;
            Vector v=(Vector)values.get(name)&#59;
            if (v==null)
            {
                v=new Vector()&#59;
            }
            if (!v.contains(value))
            {
                v.add(value)&#59;
            }
            values.put(name,v)&#59;
        }
    }
   /**字节数组中的 indexof 函数,与 String 类中的 indexOf类似
    **@para source 源字节数组
    **@para search 目标字符串
    **@para start 搜索的起始点
    **@return 如果找到,返回search的第一个字节在buffer中的下标,没有则返回-1
    **/
    private static int byteIndexOf (byte[] source,String search,int start)
    {
        return byteIndexOf(source,search.getBytes(),start)&#59;
    }

   /**字节数组中的 indexof 函数,与 String 类中的 indexOf类似
    **@para source 源字节数组
    **@para search 目标字节数组
    **@para start 搜索的起始点
    **@return 如果找到,返回search的第一个字节在buffer中的下标,没有则返回-1
    **/
    private static int byteIndexOf (byte[] source,byte[] search,int start)
    {
        int i&#59;
        if (search.length==0)
        {
            return 0&#59;
        }
        int max=source.length-search.length&#59;
        if (max<0)
            return -1&#59;
        if (start>;max)
            return -1&#59;
        if (start<0)
            start=0&#59;
    // 在source中找到search的第一个元素
    searchForFirst:
        for (i=start&#59;i<=max &#59; i++)
        {
            if (source==search[0])
            {
                //找到了search中的第一个元素后,比较剩余的部分是否相等
                int k=1&#59;
                while(k<search.length)
                {
                    if (source[k+i]!=search[k])
                    {
                        continue searchForFirst&#59;
                    }
                    k++&#59;
                }
                return i&#59;
            }
        }
        return -1&#59;
    }
    /**
    **用于从一个字节数组中提取一个字节数组
    **类似于 String 类的substring()
    **/
    private static byte[] subBytes(byte[] source,int from,int end)
    {
        byte[] result=new byte[end-from]&#59;
        System.arraycopy(source,from,result,0,end-from)&#59;
        return result&#59;
    }
    /**
    **用于从一个字节数组中提取一个字符串
    **类似于 String 类的substring()
    **/
    private static String subBytesString(byte[] source,int from,int end)
    {
        return new String(subBytes(source,from,end))&#59;
    }
    /**
    **返回字符串S转换为字节数组后的长度
    **/
    private static int bytesLen(String s)
    {
        return s.getBytes().length&#59;
    }
}



请问那位大侠知道JSP查询结果导出为excle表格,为什么只能导出14条的吗?急!! 这14条是数据库里的最后14条纪录。如果输入的数据大于14,则随机输出小于14的纪录? 这是为什么啊???请各位大侠帮忙!!!!

代码如下:

<%
String pagesize=request.getParameter("page");
int pageSize=(int)Integer.parseInt(pagesize);
System.out.println("总共导出数据是:"+pageSize+"条");
String quanxian = (String)session.getAttribute("quanxian");

//System.out.println("quanxian="+quanxian);


String searchType = request.getParameter("searchType");
String keyWord = request.getParameter("keyWord");

String strCurterPage=request.getParameter("page");//获取当前页数


if (keyWord==null){
keyWord = "";
}else{
keyWord = keyWord.replaceAll("'","");
keyWord = keyWord.replaceAll("'","''");
keyWord = new String(keyWord.getBytes("ISO8859-1"), "GB2312").trim();
}

if (searchType == null){
searchType = "";
}else{
searchType = new String(searchType.getBytes("ISO8859-1"), "GB2312").trim();
}


int curterPage;
if(strCurterPage == null){
curterPage = 1;
}else{
curterPage = java.lang.Integer.parseInt(strCurterPage);
if(curterPage<1) curterPage = 1;
}
//int pageSize = 15;

ArrayList list = log.getAllLog(pageSize,curterPage,searchType,keyWord);
int countRow = log.getCountRow();//总的行数
int countPage = log.getCountPage();//总的页数
curterPage = curterPage<countPage?curterPage:countPage;
%>

<html>
<head>
<script language="JavaScript" type="text/JavaScript">
<!--
function MM_openBrWindow(theURL,winName,features) { //v2.0
window.open(theURL,winName,features);
}

function check(){
if(document.form1.searchType.value!=""){
if( document.form1.keyWord.value==""){
alert("请输入关键词");
document.form1.keyWord.focus();
return false;
}
return true;
}
}


function delItem(ID,page){
if (window.confirm("是否确定删除?")){
window.location.href="delrizhi.jsp?id="+ID+"&page="+page;
}
}


function change(){
if(document.form1.searchType.value==""){
document.form1.keyWord.value="";
}
}

//-->
</script>

<meta http-equiv="Content-Type" content="text/html; charset=GB2312">
<title></title>
<link href="../../css/pt9.css" rel="stylesheet" type="text/css">
<script language="javascript" src="../../js/page.js"></script>
</head>

<body>

<table width="90%" border="1" cellpadding="3" cellspacing="0" class="pt9" bordercolorlight="#000000" bordercolordark="#FFFFFF">
<tr bgcolor="#39B4D7">
<td bgcolor="#3FBCF1" >
<div align="center">序号</div></td>
<td bgcolor="#3FBCF1">
<div align="center">用户</div></td>
<td bgcolor="#3FBCF1">
<div align="center">操作内容</div></td>
<td bgcolor="#3FBCF1">
<div align="center">操作时间</div></td>


<td bgcolor="#3FBCF1">
<div align="center">IP</div></td>

</tr>
<%
for(int i=0;i<list.size();i++){
LogForm info = (LogForm)list.get(i);

%>
<tr>
<td>
<div align="center"><%=((curterPage-1)*pageSize+i+1)%></div></td>
<td>
<div align="center"><%=info.getRealName()%></div></td>
<td>
<div align="center"><%=info.getActionName()%></div></td>
<td>
<div align="center"><%=info.getActionTime()%></div></td>


<td>
<div align="center"><%=info.getUserIP()%></div></td>

</tr>
<% }%>
</table>

</form>


<%

String target=request.getParameter("target");
System.out.println(target);
if(target==null)
target="";

if(!target.equals(""))
{

response.setContentType("application/vnd.ms-excel; charset=GBK");
response.setHeader("Content-Disposition","attachment; filename=\"AQEExport.xls\"");
}
else
{
response.setContentType("text/html; charset=GBK");
}

%>

</body>
</html>



1,首先,新建一个Tapestry工程文件,命名为upload,在向导里面有三个步骤,我基本是打入工程名就直接按回车了。新建好工程后,你可以看到一个典型的web目录,在 WEB-INF自动生成4个文件:

upload.appliaction tapestry的应用程序文件。

Home.html    tapestry的模版文件

Home.page    tapestry的定义的摸版的配置文件

web.xml

2.接着,再新建两个Tapestry page文件,各命名为Upload ,Download.(注意:要确认Generate an assiated HTML File,Ceate a new class被选定,对于要生成的.java我还是用Upload,Download来命名!);

对于生产.page和.jwc文件spindle提供了一个比较有用的向导,省了我好多工夫,呵呵。

3,现在就可以写代码了。

(1)Home.html

代码如下:

<html jwcid="@Shell" title="欢迎学习Tapestry!">

   <H1><FONT color="red">十分钟搞定----在Tapestry实现文件上传与下载</FONT></H1>
<body>  <p><a href="#" jwcid="@PageLink" page="Upload">上传文件</a></p>         <p><a href="#" jwcid="@PageLink" page="Dowload">下载文件</a></p>

</body></html>

(2) Upload.html

<html jwcid="@Shell" title="上传文件">
<body>
   <H1><FONT color="red">十分钟搞定----在Tapestry实现文件上传与下载</FONT></H1>
   <P><FORM jwcid="@Form" listener="ognl:listeners.submit">
     请选择你要上传的文件<input jwcid="@Upload" file="ognl:fileName" type="file"></input><INPUT type="submit" value="上传"/> 
  </FORM>
</body>
</html>

(3)Dowload.html

<html jwcid="@Shell" title="上传文件">
<body>
   <H1><FONT color="red">十分钟搞定----在Tapestry实现文件上传与下载</FONT></H1>

       <a href="#" jwcid="@DirectLink" listener="ognl:listeners.dowload">点击下载</a>
    </body>
</html>

4.到此,三个简单的html文件已经写好,接下来就实现java文件。

(1).,Upload.java

package wenone;

import org.apache.tapestry.IRequestCycle;import java.io.*;
import org.apache.tapestry.html.BasePage;
import org.apache.tapestry.request.IUploadFile;

public abstract class Upload extends BasePage
{
    public abstract IUploadFile getFile();

    public void formSubmit(IRequestCycle cycle)
    {
        IUploadFile file = getFile();

        if (file == null)
            return;

        File newFile=new File(file.getFileName());

         file.write(newFile);//存到当前工作区
        cycle.activate("Home");
    }
}

5.Dowload.java

package wenone;

import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.html.BasePage;
import java.io.*;

public abstract class Download extends BasePage{

public void download(IRequestCycle cycle)
{

   File file=new File("file.zip");
    try
    {
        HttpServletResponse response =
        cycle.getRequestContext().getResponse();


        byte[] data = new byte[1024];
        FileInputStream in = document.getFileInputstream();


        response.setHeader("Content-disposition",
          "inline; filename=" +
           document.getFileName());
        response.setContentType(file.getMimeType());
        response.setContentLength(new Long(file.getSize()).intValue());
        ServletOutputStream out = response.getOutputStream();

        while (in.read(data) > -1)
        {
            out.write(data);
        }
        in.close();
        response.flushBuffer();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}


如果只是下在某个文件的话,直接用超连接就可以搞定但是用超链不安全,谁都可以访问,用程序当然好,可是把WEB不能访问的目录的文件下载给经过认证的访问者.

前面我写过一个把图片从数据库取出来推向页面的例子.
你只要把从数据库取的数据源改成从一个文件读到的数据源,然后把文档头

"image/gif"
改成"application/x-msdownload"就可以把一个向浏览器输出一个文件了.


File t_file = new java.io.File(sourceFilePathName);
long l = t_file.length(); //文件长度
InputStream in = new FileInputStream (t_file);
if(in != null)
{
String fs = t_file.getName();
response.reset();
response.setContentType("application/x-msdownload"); //
String s = "attachment; filename="+fs; //
response.setHeader("Content-Disposition", s); //以上输出文件元信息
response.setContentLength((int)l); //设置输入文件长度
byte[] b = new byte[2048];
int len = 0;
while({len=in.read(b)) >0);
{
response.getOutputStream().write(b,0,len); //向浏览器输出
}
in.close(); //关闭文件输入流
}


有人经常会问这样一个问题:“服务器端程序如何向客户端输出一个文件,然后让浏览器

打开一个保存文件的对话框,来保存这个文件。” 当然了,一个很简单的做法,就是做一个

连接,指向要输出的文件,比如 <a href="a.rar">下载a.rar</a>,这样,当用户点击

连接的时候就会弹出IE的保存文件对话框,然后下载。



不过,这样做有两方面的缺陷:



一是,浏览器有时候会自作聪明,对于一些常见的文件类型会调用相关的应用程序打开,

比如,下载一个word文档.doc文件, 有时候浏览器会默认用word程序打开它。



二是,就是防止盗链的问题。一个用户可以直接通过url地址来随意的引用这个文件,造成

文件的盗用。



现在,在jsp中就可以直接通过文件流的方式向客户端写数据,类似于我们在asp中用到

的adodb.stream对象。这样,我们就可以把我们需要保护的文件放到Web根目录以外的地方,

比如web根目录在F:\tomcat\webapps\ROOT,而我们可以把文件放到f:\software\目录

下,这样别人就没有办法通过调用url来下载文件了。



好了,下面我们就来看看代码如何编写。



首先,设置一下response对象的contenttype为 APPLICATION/OCTET-STREAM;



接着,设置response对象的http header属性 Content-Disposition 为一个文件名,

比如: attachment; filename="a.rar" ,其中的filename是“另存为”对话框出现的

文件名。



最后,就要用 FileInputStream 对象从文件中读取数据,然后输出。

具体例子为:

<%
String filename = "JavaFlash.rar";
String filepath = "f:\\";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition","attachment; filename=\"a.rar\"");
java.io.FileInputStream fileInputStream =new java.io.FileInputStream(filepath+filename);
int i;
while ((i=fileInputStream.read()) != -1) {
out.write(i); }
fileInputStream.close();
out.close();
%>


特别值得注意的一点就是: 这种方法是直接从文件中读取数据,然后输出到客户端。 所以在整个文件中,不能再



向客户端输出任何信息,因为通过别的方式输出的信息也会保存在文件中,这样就破坏了文件的结构了。比如,

<%符号前面出现的哪怕一个空格,一个回车都不可以,所以千万要小心。
分享到:
评论

相关推荐

    API接口模板-含Word和excel

    本资源“API接口模板-含Word和excel”提供了两种格式的接口文档模板,以满足不同的工作需求。 首先,我们来看Word模板。Word是一种常见的文本编辑工具,适用于创建结构化的文档,对于长篇幅的API文档来说,它提供了...

    表格导出到work文档

    表格导出到excel经常用到,但导出到word却不常用,一旦要用到也挺烦人的,于是稍稍研究了一下,代码简单,功能更简单,勉强实现导出到word文档而已,但最重要的是能通过这些代码给操作word文档一个思路

    java web在线预览pdf、word、excel

    在IT行业中,尤其是在Web开发领域,提供用户在线预览PDF、Word、Excel等文档的功能是一项常见且实用的需求。本文将详细讲解如何利用Java Web技术实现这样的功能,主要涉及Maven构建工具、前端PDF插件以及后台...

    Winform窗体嵌入Office,打开Excel和Word

    // 隐藏Excel窗口,仅显示在Winform中 excel.Visible = false; // 创建新的工作簿 Workbook workbook = excel.Workbooks.Add(); // 获取活动工作表 Worksheet worksheet = (Worksheet)workbook.ActiveSheet; // 在A1...

    c# 操作work模版打印

    "C# 操作work模版打印"这个主题涉及到如何利用C#来处理打印任务,特别是在使用特定的工作模版(可能是Excel或Word文档)时。下面将详细阐述这个领域的相关知识点。 首先,C#中的打印功能通常依赖于.NET Framework...

    java导出文档

    #### 一、导出Excel文档概述 在Java中,导出Excel文档是一项常见的需求,尤其在处理大量数据时。本文档将详细介绍如何利用Apache POI库来实现这一功能。Apache POI是Apache软件基金会的Jakarta项目中的一个子项目,...

    Excel表格+Word文档各类各行业模板-作业标准时间测定.zip

    标题中的“Excel表格+Word文档各类各行业模板-作业标准时间测定”暗示了这个压缩包包含了一系列用于不同行业的模板,特别关注的是作业标准时间和测定方法。在企业和生产管理中,作业标准时间(Work Standard Time,...

    SpringMvc+POI 处理Excel的导入操作

    1. **Apache POI**:一个用于读写Microsoft Office文档的开源库。它支持包括Excel在内的多种Office文件格式。 2. **SpringMVC**:基于Spring框架的一个MVC架构实现,用于构建Web应用程序。 3. **MultipartRequest**...

    ipad上怎么编辑office文档.docx

    苹果 iWork 是一个 office 软件套件,包括 Pages、Numbers 和 Keynote,它们分别对应 Word、Excel 和 PowerPoint。这些应用程序可以输入和编辑 Office 文件内容,但是它们不能存成 Office 格式的文件。 苹果 iWork ...

    iwork for mac最新版2014 可更新正版

    它包含了三个主要的应用程序:Numbers(表格处理)、Pages(文字处理)及 Keynote(演示文稿),这三个应用程序分别对应微软Office中的Excel、Word和PowerPoint。iWork以其简洁直观的操作界面、强大的功能以及与iOS...

    iWork08_SN

    iWork 08是一款由苹果公司开发的办公软件套装,它包含了一系列适用于文档处理、电子表格制作以及演示文稿创建的应用程序。这些应用程序旨在提供一种简单而强大的工具集,帮助用户高效地完成各种任务。iWork 08中的...

    苹果iwork说明书

    苹果iWork是苹果公司推出的一套生产力软件套装,专为Mac系统设计,旨在提供高效、直观的文档处理、电子表格管理和演示文稿创建功能。该套装包括了Pages(文字处理)、Numbers(电子表格)和Keynote(演示文稿)三款...

    Excel表格+Word文档各类各行业模板-作业标准时间研究 表.zip

    标题中的“Excel表格+Word文档各类各行业模板-作业标准时间研究 表”指的是一个包含Excel表格和Word文档的资源包,专门针对不同行业的作业标准时间进行研究。这个压缩包可能包含了各种行业的工作流程、任务分配、...

    office_work.rar_Office_free Focus_office_work_word_word 表格

    标题中的"Office_free Focus_office_work_word_word 表格"暗示了这个压缩包包含的是与Microsoft Office相关的免费资源,特别是Word文档和表格编辑。描述提到是"word形式的办公表格文档 量很大 free下载",这表明...

    work7(林今奕).zip

    2. **Microsoft Office 文件** (.docx, .xlsx, .pptx):可能包括Word文档、Excel电子表格和PowerPoint演示文稿,用于撰写报告、分析数据或制作演讲稿。 3. **编程文件** (.cpp, .java, .py): 如果是编程作业,那么会...

    SAS学习系列04.-导入数据Ⅱ——Excel文件.pdf

    SAS学习系列04.-导入数据Ⅱ——Excel文件 本节内容主要讲述了使用...PROC IMPORT OUT= WORK.RESULTS DATAFILE= "D:\我的文档\My SAS Files\9.3\exercise.xlsx" DBMS=EXCEL REPLACE; RANGE="tests1"; GETNAMES=YES;

    EXCEL高二计算机期末考试试卷.pdf

    - A..DOC、B..TXT、C..XLS、D..DOT是文件扩展名,分别代表文档(Word)、文本文件、Excel表格、模板(Word)。 - 选择题中出现了多个选项组合(如A、B、C、D)以及操作指令(如Ctrl+A),这些都是Excel中的常用...

    SAS学习系列04.-导入数据Ⅱ——Excel文件.docx

    SAS学习系列04.-导入数据Ⅱ——Excel文件.docx 本篇文章主要讲解了使用SAS导入Excel文件的两种方法...PROC IMPORT OUT= WORK.RESULTS DATAFILE= "D:\我的文档\My SAS Files\9.3\exercise.xlsx" DBMS=EXCEL REPLACE;

    Work01.rar

    在本例中,“Work01”可能是用户为一组工作文档创建的归档,可能是为了组织项目、任务或日常工作的文件。 描述中同样提到“Work01.rar”,这暗示了压缩包可能包含了与某个项目或工作任务相关的多种文件。由于没有...

    ssh_workorder.rar

    由于压缩包内的文件名称只给出"workorder",我们可以推测这可能是一个包含多个文档或脚本的集合,比如: 1. **工作订单模板**:可能有Excel或PDF格式的文件,定义了工作订单的标准格式和所需信息,如任务描述、...

Global site tag (gtag.js) - Google Analytics