細心!用心!耐心!

          吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學業,五六點粗墨,七八筆買賣,九十道人情。

          BlogJava 聯系 聚合 管理
            1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks

          [精華] jsp中下載程序問題


          http://www.chinaunix.net 作者:huangmw  發表于:2002-12-24 11:18:22
          發表評論】【查看原文】【Java討論區】【關閉

          我下載了jspsmartupload類,然后編寫了下載程序,如下:
          <%@page contentType=&quot;text/html;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);
          mySmartUpload.downloadFile(&quot;d:\\111.txt&quot;);
          %>;
          運行后,我txt文件中的內容就直接顯示在了頁面上,zip文件也同樣,只不過是亂碼,有什么辦法不顯示而和一般的下載一樣呢?



           eclipse 回復于:2002-10-18 10:54:22

          應該是SmartUpload類的問題,JSP程序沒有問題,我感覺


           huangmw 回復于:2002-10-18 11:27:17

          這個類是從www.jspsmart.com站點下載的,不會他們編的類問題吧?
          你能提供一個類似這種類給我嗎?謝謝了


           eclipse 回復于:2002-10-18 12:11:30

          TestFileDownload.JSP頁面的例子:

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

          // 設置響應頭和下載保存的文件名
          response.setContentType(”APPLICATION/OCTET-STREAM”);
          response.setHeader(”Content-Disposition”,
          ”attachment; filename=\”” + filename + ”\””);

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

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

          值得注意的是:在你要下載的文件內容里,除了文件的內容之外,不應該再附加有其它任何的字符,包括空格和回車換行符。我們有時在編寫代碼的時候,為了使代碼清晰可讀,往往會添加一些空格、制表符或者回車換行符,這樣雖然看起來比較清晰,但有時可能會得不到正確的結果。比如:
          <%@ 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;
          import java.io.*;
          /**一個存放文件信息的類,包括文件的名稱(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;
              byte[] buffer;
              String fileName;
              String parameterName;

              FileHolder(byte[] buffer, String contentType, String fileName, String parameterName)
              {
                  this.buffer = buffer;
                  this.contentType = contentType;
                  this.fileName = fileName;
                  this.parameterName = parameterName;
              }
              /**把文件的內容存到指定的文件中,
              **<b>;這個方法不會檢查這個文件是否可寫、是否已經存在。</b>;
              **@param file  目的文件
              **@throws 在 I/O 操作中被拋出的 IOException
              **/
              public void saveTo(File file) throws IOException
              {
                  BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
                  out.write(buffer);
                  out.close();
              }

              /**把文件的內容存到指定的文件中,
              **<b>;這個方法不會檢查這個文件是否可寫、是否已經存在。</b>;
              **@param name 目的文件名
              **@throws 在 I/O 操作中被拋出的 IOException
              **/
              public void saveTo(String name) throws IOException
              {
                  saveTo(new File(name));
              }

             /**
              **返回一個文件內容的字節數組
              **@return 一個代表文件內容的字節數組
             **/
              public byte[] getBytes()
              {
                  return buffer;
              }

             /**
              **返回該文件在文件上載前在客戶端的名稱
              **@return 該文件在文件上載前在客戶端的名稱
             **/
              public String getFileName()
              {
                  return fileName;
              }

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

             /**
              **返回上載該文件時,Html 頁面窗體中 file 控件的 name 屬性
              **@return 返回上載該文件時,Html 頁面窗體中 file 控件的 name 屬性
             **/
              public String getParameterName()
              {
                  return parameterName;
              }
          }


           eclipse 回復于:2002-10-18 12:22:31

          存放報文內容的類:

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

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

             /**
               *返回一個 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);
                  if(v != null)
                  {
                    return (FileHolder)v.elementAt(0);
                  }
                  return null;
              }
              /**
               * 返回一個 由 String 對象構成的 Enumeration ,包含了 Html 頁面
               *窗體中所有 file 控件的 name 屬性。
               *如果窗體中沒有 file 控件,則返回一個空的 Enumeration
               * @return             返回一個 由 String 對象構成的 Enumeration ,包含了 Html 頁面
               *窗體中所有 file 控件的 name 屬性。
               *如果窗體中沒有 file 控件,則返回一個空的 Enumeration
               */
              public Enumeration getFileParameterNames()
              {
                  return files.keys();
              }
             /**
               *返回一個 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);
                  if(v!=null)
                  {
                      FileHolder[] result=new FileHolder[v.size()];
                      v.toArray(result);
                      return result;
                  }
                  return new FileHolder[0];
              }
              //------------->;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);
              }
                  /**
              **返回根據當前請求生成的一個 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();
                Hashtable files = new Hashtable();
                String contentType = request.getContentType();
                int contentLength = request.getContentLength();
                if (contentLength >; maxLength)
                {
                  ContentFactoryException e=new ContentFactoryException(&quot;上傳數據太多,請不要選擇太大的文件&quot;);
                  throw e;
                }
                if(contentType == null || !contentType.startsWith(&quot;multipart/form-data&quot;))
                {
                  return null;
                }
          //get out the boudary from content-type
                int start = contentType.indexOf(&quot;boundary=&quot;);
          //這里應該
                int boundaryLen = new String(&quot;boundary=&quot;).length();
                String boundary = contentType.substring(start + boundaryLen);
                boundary = &quot;--&quot; + boundary;
          //用字節表示,以免 String  和 byte 數組的長度不一致
                boundaryLen = bytesLen(boundary);
          //把request 中的數據讀入一個byte數組
                byte buffer[] = new byte[contentLength];
                int once = 0;
                int total = 0;
                DataInputStream in = new DataInputStream(request.getInputStream());
                while((total < contentLength) &amp;&amp; (once >;= 0))
                {
                  once = in.read(buffer, total, contentLength);
                  total += once;
                }
          //對buffer中的數據進行拆分
                int pos1 = 0;                  //pos1 記錄 在buffer 中下一個 boundary 的位置
          //pos0,pos1 用于 subBytes 的兩個參數
                int pos0 = byteIndexOf(buffer, boundary, 0);//pos0 記錄 boundary 的第一個字節在buffer 中的位置
                do
                {
                  pos0 += boundaryLen;                                 //記錄boundary后面第一個字節的下標
                  pos1 = byteIndexOf(buffer, boundary, pos0);
                  if(pos1==-1)
                  {
                    break;
                  }//
                  pos0 += 2;//考慮到boundary后面的 \r\n
                  parse(subBytes(buffer, pos0, pos1-2), values, files);      //考慮到boundary后面的\r\n
                  pos0=pos1;
                }while(true);
                return new ContentFactory(values,files);
              }

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

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

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

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

                  for (int i=0;i<tokens.length ;i++ )
                  {
                      position=byteIndexOf(buffer,tokens,0);
                  }
                  if (position[1]>;0 &amp;&amp; position[1]<position[2])
                  {
                      //包含tokens 中的第二個元素,說明是個文件數據段
                      //1.得到字段名
                      String name =subBytesString(buffer,position[0]+bytesLen(tokens[0]),position[1]);
                      //2.得到文件名
                      String file= subBytesString(buffer,position[1]+bytesLen(tokens[1]),position[2]);
                      if (file.equals(&quot;&quot;)) return;
                      file=new File(file).getName();     //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]);
                     //4.得到文件內容
                      byte[] b=subBytes(buffer,position[4]+bytesLen(tokens[4]),buffer.length);
                      FileHolder f=new FileHolder(b,contentType,file,name);
                      Vector v=(Vector)files.get(name);
                      if (v==null)
                      {
                          v=new Vector();
                      }
                      if (!v.contains(f))
                      {
                          v.add(f);
                      }
                      files.put(name,v);
                      //同時將 name 屬性和 file 屬性作為普通字段,存入values;
                      v=(Vector)values.get(name);
                      if (v==null)
                      {
                          v=new Vector();
                      }
                      if (!v.contains(file))
                      {
                          v.add(file);
                      }
                      values.put(name,v);
                  }else
                  {
          //            String[] tokens={&quot;name=\&quot;&quot;,&quot;\&quot;; 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]);
                      String value= subBytesString(buffer,position[4]+bytesLen(tokens[4]),buffer.length);
                      Vector v=(Vector)values.get(name);
                      if (v==null)
                      {
                          v=new Vector();
                      }
                      if (!v.contains(value))
                      {
                          v.add(value);
                      }
                      values.put(name,v);
                  }
              }
             /**字節數組中的 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);
              }

             /**字節數組中的 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;
                  if (search.length==0)
                  {
                      return 0;
                  }
                  int max=source.length-search.length;
                  if (max<0)
                      return -1;
                  if (start>;max)
                      return -1;
                  if (start<0)
                      start=0;
              // 在source中找到search的第一個元素
              searchForFirst:
                  for (i=start;i<=max ; i++)
                  {
                      if (source==search[0])
                      {
                          //找到了search中的第一個元素后,比較剩余的部分是否相等
                          int k=1;
                          while(k<search.length)
                          {
                              if (source[k+i]!=search[k])
                              {
                                  continue searchForFirst;
                              }
                              k++;
                          }
                          return i;
                      }
                  }
                  return -1;
              }
              /**
              **用于從一個字節數組中提取一個字節數組
              **類似于 String 類的substring()
              **/
              private static byte[] subBytes(byte[] source,int from,int end)
              {
                  byte[] result=new byte[end-from];
                  System.arraycopy(source,from,result,0,end-from);
                  return result;
              }
              /**
              **用于從一個字節數組中提取一個字符串
              **類似于 String 類的substring()
              **/
              private static String subBytesString(byte[] source,int from,int end)
              {
                  return new String(subBytes(source,from,end));
              }
              /**
              **返回字符串S轉換為字節數組后的長度
              **/
              private static int bytesLen(String s)
              {
                  return s.getBytes().length;
              }
          }


           huangmw 回復于:2002-10-18 16:13:53

          好長的一篇代碼,只有慢慢看了,不過還是謝謝


           eclipse 回復于:2002-10-18 16:19:10

          最后邊兩篇有興趣了看,沒興趣了就不要看了,是我擴展的

          三四五等幾貼我想可以解決你的問題了,不過不是smart。

          其實你可以將下載的smart反編譯,看看具體代碼,或者重新下載試試



           huangmw 回復于:2002-10-18 16:26:19

          呵呵,好的,謝謝,不過怎么反編譯呢?啊。。。不要打我。。。菜鳥無罪


           eclipse 回復于:2002-10-18 16:39:21

          談談JAVA的反編譯 
           
          談談JAVA的反編譯
          于瑤
          如今JAVA語言在全世界范圍正如火如荼般的流行,它廣范地應用在INTERNET的數據庫、多媒體、CGI、及動態網頁的制作方面。1999年在美國對JAVA程序員的需求量首次超過C++!
          作者因最近分析一些JAVA程序,對JAVA的反編譯進行了一番了解,下面將我所了解的情況作以下介紹,希望對JAVA愛好者有所幫助。
          JAVA是采用一種稱做“字節編碼”的程序結構,分為小程序(嵌入到HTML文件中)和應用程序(直接在命令狀態下執行)兩種類型。無論哪種結構,一旦用JAVAC 命令編譯后,均變成后綴為CLASS的同名可執行文件。這種文件是不可閱讀的代碼。
          經查閱了SUN公司的JDK(JDK1.1.3)文檔資料后,我找到了一個據稱是可反編譯JAVA的JAVAP文件(EXE),這個文件位于\JDK\BIN\ 下面,經按說明使用后,感到失望,原來這個“反編譯”僅可反編譯出JAVA程序的數據區(定義)、若干方法和類的引用等。
          這里我用了一個簡單例子來說明問題。
          JAVA的源程序hello_java.java如下:

          import java.applet.*;
          import java.awt.*;

          public class hello_java extends Applet
          {
          public void paint(Graphics g)
          {
          g.drawString(&quot;Hello Java!\n&quot;,20,20);
          }


          經用反編譯命令:javap -c -package -public -private hello_java hello.java 
          得到的反編譯結果(hello.java)如下:(有關javap命令的選擇參數請見其使用說明,這里-c表示選擇了反編譯)

          Compiled from hello_java.java
          public synchronized class hello_java extends java.applet.Applet 
          /* ACC_SUPER bit set */
          {
          public void paint(java.awt.Graphics);
          public hello_java();

          Method void paint(java.awt.Graphics)
          0 aload_1
          1 ldc #1 <String &quot;Hello Java!
          &quot;>;
          3 bipush 20
          5 bipush 20
          7 invokevirtual #6 <Method java.awt.Graphics.drawString(Ljava/lang/String;II)V>;
          10 return

          Method hello_java()
          0 aload_0
          1 invokespecial #5 <Method java.applet.Applet.<init>;()V>;
          4 return
          }

          從上述結果不難看出該反編譯未能將源程序全譯出來,像語句g.drawString(&quot;Hello Java!\n&quot;,20,20); 就沒有。隨著程序量增加,未能編譯的JAVA語句還會更多。所以這個反編譯程序僅能起個參考作用。
          幸虧有了INTERNET,筆者通過YAHOO很快找到了一個JAVA反編譯“自由軟件”(SHAREWARE),http://www.inter.nl.net/users/H.P.van.Vliet/mocha.htm 。 這個軟件叫MOCHA,據說是一位30來歲的加拿大的研究生所完成,僅是個“?”版,原因是這位叫做H.P.VAN.VLIET的小伙子患癌逝世了,十分可惜呀!
          經使用MOCHA反編譯軟件,感到這個軟件十分好用,筆者試反編譯多個JAVA程序,均得到很好的結果。
          這里給出如何使用這個軟件,首先,用WINZIP等將&quot;mocha-b1.zip&quot; 解開得到&quot;mocha.zip&quot;文件,&quot;mocha.zip&quot;不須再解開,這個包內包括了反編譯的類文件,只需將其拷貝到JDK所在的目錄下,如:c:\jdk\bin\ 此外,須設置路徑:SET CLASSPATH=c:\myclasses;c:\jdk\bin\mocha.zip
          MOCHA用法:
          java mocha.Decompiler [-v] [-o] Class1.class Class2.class ...
          &quot;java&quot; 調用Java虛擬機 
          &quot;mocha.Decompiler&quot; 指示要進行JAVA反編譯
          &quot;-v&quot; 選擇詳細輸出
          &quot;-o&quot; 選寫入已有的.mocha 文件
          &quot;ClassX.class&quot; 指出要反編譯類名
          注意,不需給出輸出的JAVA文件名,因為MOCHA自動產生一個與CLASS同名但擴展名為MOCHA的JAVA源文件。
          對于上例,可用命令:
          java mocha.Decompiler [-v] [-o] hello_java.class
          得到的源文件:
          /* Decompiled by Mocha from hello_java.class */
          /* Originally compiled from hello_java.java */

          import java.applet.Applet;
          import java.awt.Graphics;

          public synchronized class hello_java extends Applet
          {
          public void paint(Graphics g)
          {
          g.drawString(&quot;Hello Java!\n&quot;, 20, 20);
          }

          public hello_java()
          {
          }
          }
          我們不難發現,此文件與編譯前的JAVA源文件完全一樣!筆者曾經用MOCHA反編譯出最大為80K的源文件,均取得成功。
          在此,筆者向英年早逝的VLIET表示敬意,感謝他給我們留下這個工具軟件。
          如讀者下載MOCHA有困難,可給筆者來電子郵件,筆者可將MOCHA寄去。
          posted on 2007-07-16 23:23 張金鵬 閱讀(720) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 县级市| 民县| 江孜县| 华蓥市| 新宾| 凉城县| 中方县| 周口市| 兴安盟| 班玛县| 永福县| 射阳县| 八宿县| 太和县| 张掖市| 焦作市| 铜川市| 江源县| 小金县| 淳化县| 洞口县| 青铜峡市| 南靖县| 汝城县| 万山特区| 历史| 苏尼特左旗| 沾益县| 崇信县| 永宁县| 精河县| 会宁县| 磐石市| 普兰店市| 安国市| 中宁县| 桃源县| 白山市| 阿拉尔市| 阳朔县| 互助|