免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5317 | 回复: 13
打印 上一主题 下一主题

jsp中下载程序问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2002-10-17 20:54 |只看该作者 |倒序浏览
我下载了jspsmartupload类,然后编写了下载程序,如下:
<%@page contentType=&quot;text/html&#59;charset=gb2312&quot;%>;<%@page language=&quot;java&quot; import=&quot;com.jspsmart.upload.*&quot;%>;<jsp:useBean id=&quot;mySmartUpload&quot; scope=&quot;page&quot; class=&quot;com.jspsmart.upload.SmartUpload&quot;/>;<%mySmartUpload.initialize(pageContext)&#59;
mySmartUpload.downloadFile(&quot;d:\\111.txt&quot&#59;
%>;
运行后,我txt文件中的内容就直接显示在了页面上,zip文件也同样,只不过是乱码,有什么办法不显示而和一般的下载一样呢?

论坛徽章:
0
2 [报告]
发表于 2002-10-18 10:54 |只看该作者

jsp中下载程序问题

应该是SmartUpload类的问题,JSP程序没有问题,我感觉

论坛徽章:
0
3 [报告]
发表于 2002-10-18 11:27 |只看该作者

jsp中下载程序问题

这个类是从www.jspsmart.com站点下载的,不会他们编的类问题吧?
你能提供一个类似这种类给我吗?谢谢了

论坛徽章:
0
4 [报告]
发表于 2002-10-18 12:11 |只看该作者

jsp中下载程序问题

TestFileDownload.JSP页面的例子:

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

// 设置响应头和下载保存的文件名
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” />;

论坛徽章:
0
5 [报告]
发表于 2002-10-18 12:13 |只看该作者

jsp中下载程序问题

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

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

论坛徽章:
0
6 [报告]
发表于 2002-10-18 12:17 |只看该作者

jsp中下载程序问题

如果不用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;
    }
}

论坛徽章:
0
7 [报告]
发表于 2002-10-18 12:22 |只看该作者

jsp中下载程序问题

存放报文内容的类:

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;
    }
}

论坛徽章:
0
8 [报告]
发表于 2002-10-18 16:13 |只看该作者

jsp中下载程序问题

好长的一篇代码,只有慢慢看了,不过还是谢谢

论坛徽章:
0
9 [报告]
发表于 2002-10-18 16:19 |只看该作者

jsp中下载程序问题

最后边两篇有兴趣了看,没兴趣了就不要看了,是我扩展的

三四五等几贴我想可以解决你的问题了,不过不是smart。

其实你可以将下载的smart反编译,看看具体代码,或者重新下载试试

论坛徽章:
0
10 [报告]
发表于 2002-10-18 16:26 |只看该作者

jsp中下载程序问题

呵呵,好的,谢谢,不过怎么反编译呢?啊。。。不要打我。。。菜鸟无罪
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP