GONE WITH THE WIND

          --tomorrow is another day

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            30 隨筆 :: 19 文章 :: 0 評(píng)論 :: 0 Trackbacks

          #

          1.作用的范圍不同:

          1)inverse :<set/>,<map/>,<list/>,<array/>,<bag/>

          2)cascade :<many-to-one>,<one-to-one/>,<set/>,<map/>,<list/>,<array/>,<bag/>.

          2.執(zhí)行策略不同

          1)inverse :首先判斷集合的變化情況,然后針對(duì)變化執(zhí)行相應(yīng)的處理。

          2)cascade :直接對(duì)集合中的每個(gè)元素執(zhí)行相應(yīng)的處理。

          3.執(zhí)行的時(shí)機(jī)不同

          1)inverse :在執(zhí)行SQL語(yǔ)句之前判斷是否要執(zhí)行該SQL語(yǔ)句。

          2)cascade :在主控方發(fā)生操作時(shí)用來(lái)判斷是否進(jìn)行級(jí)聯(lián)操作。

          4.執(zhí)行的目標(biāo)不同

          1)inverse :對(duì)于<one-to-many>處理被管理表,<many-to-many/>處理中間表。

          2)cascade :都只只對(duì)被關(guān)聯(lián)表。

          總結(jié):書(shū)上說(shuō)了inverse 一對(duì)多的時(shí)候最好把多的一方設(shè)置成false由一的一方來(lái)控制;cascade盡量別使,進(jìn)行顯示的添加刪除。

          posted @ 2009-03-30 16:46 張永耀 閱讀(177) | 評(píng)論 (0)編輯 收藏

          構(gòu)造這樣一個(gè)例子,在測(cè)試過(guò)程中來(lái)說(shuō)明一些Hibernate的高級(jí)配置及其相關(guān)機(jī)制:
          有三個(gè)類(lèi):Category.java,Prodcuct.java,ConfigurationTest.java,其中第三個(gè)類(lèi)是用來(lái)測(cè)試的。
          Category.java代碼:
                 

          package unsaved_value;    
          import ......    
          public class Category {    
              private Integer id;    
              private String name;    
              private String description;    
              private Set products;    
              public Category(){    
                   id=null;    
                   name=null;    
                  description=null;    
                  products=new HashSet ();    
               }    
               public void addProduct(Product p){    
                   products.add(p);    
              }    
               //**********setter and getter    
              ........    
          }   


          Product.java代碼:


          package unsaved_value;      
          public class Product {      
              private Integer id;      
              private String name;      
              private Category category;      
              private String description;      
              public Product(){     
                   
              }      
               //*******getter and setter      
               .........      
          }      

          ConfigurationTest.java

          public void testSave()throws Exception{    
                  Category category=new Category();    
                  category.setName("java編程書(shū)籍2");    
                  category.setDescription("編程經(jīng)典書(shū)籍2");    
                  Product pro=new Product();    
                  pro.setName("java編程思想2");    
                  pro.setDescription("第四版中文版2");     
                  pro.setCategory(category);    
                  category.addProduct(pro);    
                  Transaction tx=session.beginTransaction();    
                  assert (session!=null):("session is null");    
                  session.save(category);    
                  tx.commit();    
              }    

               
          Category代表產(chǎn)品目錄,而Product代表產(chǎn)品,顯然Category與Product是一對(duì)多的關(guān)系。Hibernate在映射一對(duì)多關(guān)系時(shí),有兩種方式,一種是單向一對(duì)多,一種是雙向關(guān)系。兩者相比,雙向一對(duì)多的好處體現(xiàn)在兩方面:首先,也是很明顯的一點(diǎn),由于是雙向關(guān)聯(lián),我們?cè)趯?shí)際業(yè)務(wù)邏輯時(shí)將更方便,例如我們可以檢索一個(gè)Category下的所有Product,同時(shí)還可以檢索出Product屬于哪個(gè)。其次,雙向關(guān)系相對(duì)單向關(guān)系而言,在數(shù)據(jù)庫(kù)的訪問(wèn)方面更有優(yōu)勢(shì)。這一點(diǎn)留在后面講inverse時(shí)講
          。雙向關(guān)聯(lián)比單向關(guān)聯(lián)唯一的”劣勢(shì)“,就在于雙向關(guān)聯(lián)需要比單向關(guān)聯(lián)多寫(xiě)一個(gè)映射文件,這不問(wèn)題。使用雙向關(guān)聯(lián)實(shí)現(xiàn)這兩個(gè)類(lèi)同數(shù)據(jù)庫(kù)的映射:

          Category.hbm.xml:  
          version="1.0" encoding="UTF-8"?>  

          " <hibernate-mapping package="unsaved_value">  
             <class name="Category" table="category">  
               <id name="id" column="id">  
                 <generator class="native">generator>  
               id>  
               
               <property name="name" column="name"/>  
               <property name="description" column="description"/>


               <set name="products" table="product" lazy="true" inverse="true" cascade="all">  
                   <key column="category"/>  
                      <one-to-many class="Product"/>  
               set>  
               
             class>  
          hibernate-mapping>  
            
          Product.hbm.xml:


          version="1.0" encoding="UTF-8"?>    
          "
          <hibernate-mapping package="unsaved_value">    
          <class name="Product" table="product">    
               <id name="id" column="id" unsaved-value="null">    
                   <generator class="native">generator>    
               id>    
                   
               <property name="name" column="name"/>    
               <property name="description" column="description"/>    
                 
               <many-to-one name="category"    
                            column="category"     
                            class="Category"    
               />    
             class>    
          hibernate-mapping>    
                  
          現(xiàn)在把這個(gè)例子所牽涉到的知識(shí)一一展開(kāi):
          一.inverse
              該詞的譯意是“反轉(zhuǎn)”,反轉(zhuǎn)什么——反轉(zhuǎn)控制端,這項(xiàng)配置決定了由關(guān)聯(lián)雙方中的哪一方來(lái)維持關(guān)聯(lián)關(guān)系(在數(shù)據(jù)庫(kù)中表現(xiàn)為外鍵約束)。上述配置中,在Category.hbm.xml中將inverse設(shè)置為true,意思是說(shuō)“我需要反轉(zhuǎn)(控制端)”,反轉(zhuǎn)的結(jié)果是由對(duì)方即Product來(lái)維持關(guān)聯(lián)關(guān)系。用單向關(guān)聯(lián)更容易說(shuō)明”維持關(guān)聯(lián)關(guān)系“是什么意思:考慮用單向關(guān)系來(lái)實(shí)現(xiàn)這個(gè)映射關(guān)系的情況,即由Category關(guān)聯(lián)到Product,考慮下面的代碼:

          Product p=new Product();  
          ..setXXX  
          Category c=new Category();  
          ..設(shè)置Category的屬性  
          c.addProduct(p);//建立起了c和p的關(guān)聯(lián)關(guān)系  
          session.save(c);  

          會(huì)執(zhí)行三條SQL語(yǔ)句:兩條插入語(yǔ)句,分別插入c和p,然后還有一條update語(yǔ)句建立起c和p的關(guān)聯(lián)(更新p的外鍵)。上面,我們說(shuō)由Category端控制關(guān)聯(lián),因此p.setCategory(c)這樣一句話是沒(méi)用的,它并不會(huì)導(dǎo)致在插入p的時(shí)候就設(shè)置p的外鍵以建立起兩者的關(guān)聯(lián)關(guān)系,從而節(jié)省一條update語(yǔ)句。同時(shí)我們還會(huì)看到,如果在數(shù)據(jù)庫(kù)模式中將p的外鍵設(shè)置成非空,這些代碼將不能執(zhí)行,因?yàn)樵诓迦雙時(shí),由于c和p的關(guān)聯(lián)關(guān)系還未建立起來(lái),因此p的外鍵為空。回到雙向關(guān)聯(lián)上來(lái),為了更清楚地明白inverse在雙向關(guān)聯(lián)中到底起什么作用,我們分別將其值設(shè)為true和false,看看打印出的的SQL有何區(qū)別:

          inverse=true時(shí)的打印結(jié)果:

          Hibernate: insert into category (name, description) values (?, ?)  
          Hibernate: insert into product (name, description, category) values (?, ?, ?)   
          inverse=false時(shí)的打印結(jié)果:

          Hibernate: insert into category (name, description) values (?, ?)    
          Hibernate: insert into product (name, description, category) values (?, ?, ?)    
          Hibernate: update product set category=? where id=?   
                 為什么inverse=true時(shí)會(huì)比inverse=false時(shí)少執(zhí)行一條SQL語(yǔ)句?這是由控制端的不同造成的。前者說(shuō)"我要反轉(zhuǎn)控制,由Product來(lái)控制關(guān)聯(lián)",因此在將p對(duì)象insert時(shí),p已經(jīng)設(shè)置了其category字段,從而建立了關(guān)聯(lián)關(guān)系,而后者說(shuō)"我不反轉(zhuǎn)控制,由我自己來(lái)控制關(guān)聯(lián)",因此在將p對(duì)象insert后,c為了維持兩者的關(guān)聯(lián),還要去執(zhí)行一次update,以更新p的外鍵,從而建立起兩者的關(guān)聯(lián)關(guān)系。
          結(jié)論:對(duì)于一對(duì)多雙向關(guān)系,始終在“一”那一方將其inverse設(shè)置成true,這樣會(huì)提高性能。

          二.cascade
             級(jí)聯(lián)。當(dāng)關(guān)聯(lián)的"一"方進(jìn)行某種動(dòng)作(更新,刪除)時(shí),"多"方即使沒(méi)有顯式地進(jìn)行編碼,它也會(huì)自動(dòng)進(jìn)行同樣的動(dòng)作。cascade的可選值有:
          all : 所有情況下均進(jìn)行關(guān)聯(lián)操作。即是save-update + delete
          none:所有情況下均不進(jìn)行關(guān)聯(lián)操作。這是默認(rèn)值。
          save-update:在執(zhí)行save/update/saveOrUpdate時(shí)進(jìn)行關(guān)聯(lián)操作。
          delete:在執(zhí)行delete時(shí)進(jìn)行關(guān)聯(lián)操作。
          all-delete-orphan:A:級(jí)聯(lián)save-update B級(jí)聯(lián)delete C:刪除所有孤兒項(xiàng)(orphan孤兒)。先看看父子關(guān)系,例如在Customer和Order的模型中,這兩者便是父子關(guān)系,當(dāng)一個(gè)Customer的生命周期決定Order的生命周期,如果一個(gè)Customer不在了,其相關(guān)的Order繼續(xù)存在是毫無(wú)業(yè)務(wù)意義的。刪除所有孤兒項(xiàng)的意思即是,刪除所有與父對(duì)象失去關(guān)聯(lián)關(guān)系的子對(duì)象。

          三.lazy
              是否延遲加載。一般來(lái)說(shuō),應(yīng)該延遲加載,即將lazy設(shè)為true。延遲加載的相關(guān)點(diǎn)很多,這在另外的學(xué)習(xí)筆記中總結(jié)。

          四.unsaved-value
              以上是"一"方的重要配置,再看看"多"方的一個(gè)重要配置:unsaved-value,就像上面Product.hbm.xml中的設(shè)置那樣,這一項(xiàng)在id的配置中設(shè)置。這一設(shè)置是與級(jí)聯(lián)一起工作的。關(guān)于這一點(diǎn),robbin講的很清楚:
          當(dāng)你顯式的使用session.save()或者session.update()操作一個(gè)對(duì)象的時(shí)候,實(shí)際上是用不到unsaved-value 的。某些情況下(父子表關(guān)聯(lián)保存),當(dāng)你在程序中并沒(méi)有顯式的使用save或者update一個(gè)持久對(duì)象,那么Hibernate需要判斷被操作的對(duì)象究竟是一個(gè)已經(jīng)持久化過(guò)的持久對(duì)象,是一個(gè)尚未被持久化過(guò)的內(nèi)存臨時(shí)對(duì)象。例如:
                 Session session = ...;
          Transaction tx = ...;  
          Parent parent = (Parent) session.load(Parent.class, id);  
          Child child = new Child();  
          child.setParent(parent);  
          child.setName("sun");  
          parent.addChild(child);  
          s.update(parent);  
          s.flush();  
          tx.commit();  
          s.close();  
               在上例中,程序并沒(méi)有顯式的session.save(child); 那么Hibernate需要知道child究竟是一個(gè)臨時(shí)對(duì)象,還是已經(jīng)在數(shù)據(jù)庫(kù)中有的持久對(duì)象。如果child是一個(gè)新創(chuàng)建的臨時(shí)對(duì)象(本例中就是這種情況),那么Hibernate應(yīng)該自動(dòng)產(chǎn)生session.save(child)這樣的操作,如果child是已經(jīng)在數(shù)據(jù)庫(kù)中有的持久對(duì)象,那么 Hibernate應(yīng)該自動(dòng)產(chǎn)生session.update(child)這樣的操作。因此我們需要暗示一下Hibernate,究竟 child對(duì)象應(yīng)該對(duì)它自動(dòng)save還是update。在上例中,顯然我們應(yīng)該暗示Hibernate對(duì)child自動(dòng)save,而不是自動(dòng) update。那么Hibernate如何判斷究竟對(duì)child是save還是update呢?它會(huì)取一下child的主鍵屬性 child.getId() ,這里假設(shè)id是 java.lang.Integer類(lèi)型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate認(rèn)為 child是新的內(nèi)存臨時(shí)對(duì)象,發(fā)送save,如果不相等,那么Hibernate認(rèn)為child是已經(jīng)持久過(guò)的對(duì)象,發(fā)送update。unsaved-value="null" (默認(rèn)情況,適用于大多數(shù)對(duì)象類(lèi)型主鍵 Integer/Long/String/...)
          當(dāng)Hibernate取一下child的Id,取出來(lái)的是null(在上例中肯定取出來(lái)的是null),和unsaved-value設(shè)定值相等,發(fā)送save(child)
          當(dāng)Hibernate取一下child的id,取出來(lái)的不是null,那么和unsaved-value設(shè)定值不相等,發(fā)送update(child)
             unsaved-value的可選配置有:
          none,any,null
          unsaved-value="none"和unsaved-value="any"主要用在主鍵屬性不是通過(guò)Hibernate生成,而是程序自己setId()的時(shí)候。unsaved-value="none"和unsaved-value="any"究竟有什么含義了。如果你非要用assigned不可,那么繼續(xù)解釋一下:
          unsaved-value="none" 的時(shí)候,由于不論主鍵屬性為任何值,都不可能為none,因此Hibernate總是對(duì)child對(duì)象發(fā)送update(child)
          unsaved-value="any" 的時(shí)候,由于不論主鍵屬性為任何值,都肯定為any,因此Hibernate總是對(duì)child對(duì)象發(fā)送save(child)
                大多數(shù)情況下,可以避免使用assigned,只有當(dāng)你使用復(fù)合主鍵的時(shí)候不得不手工setId(),這時(shí)候需要你自己考慮究竟怎么設(shè)置unsaved-value了,根據(jù)你自己的需要來(lái)定。
                關(guān)于為什么不要使主鍵帶有義務(wù)意義,robbin的解釋很清楚:還是以上面的例子打比方,如果我們將Category的某一個(gè)性質(zhì)(比如產(chǎn)品序號(hào)或者名稱(chēng))作為主鍵,如果后來(lái)由于業(yè)務(wù)需要,我們把這個(gè)性質(zhì)改了,那將不可僻免地要去修改與這個(gè)對(duì)象相關(guān)聯(lián)的所有數(shù)據(jù)的外鍵,而如果我們只要代理主鍵,這個(gè)問(wèn)題就可完全僻免。


          今天在寫(xiě)程序的時(shí)候發(fā)現(xiàn)了一個(gè)很奇怪的問(wèn)題“ResultSet can not re-read row data for column”,用google一搜,原來(lái)是微軟公司的驅(qū)動(dòng)的兼容性不太好。有熱心人總結(jié)了微軟驅(qū)動(dòng)的缺點(diǎn):(1)如果采用jdbc-odbc驅(qū)動(dòng),那么就必須按照查詢(xún)順序來(lái)一次讀取(不論有沒(méi)有image或text,ntext類(lèi)型)(2)如果采用微軟提供的ms sql server jdbc driver,如果查詢(xún)語(yǔ)句中,不存在image或text,ntext類(lèi)型字段,那么可以按照無(wú)序獲取(3)如果采用微軟提供的ms sql server jdbc driver,如果查詢(xún)語(yǔ)句中,存在image或text,ntext類(lèi)型字段,那么就必須按照順序讀取,否則就會(huì)報(bào)告Driver]ResultSet can not re-read row data for column之類(lèi)的錯(cuò)誤(4)如果想不查詢(xún)語(yǔ)句中有沒(méi)有image或text,,ntext類(lèi)型字段,都可以不按照順序獲取,或重復(fù)獲取。那么就必須更換驅(qū)動(dòng),改用第三方的。 最后,我改用了第三方的驅(qū)動(dòng)。測(cè)試成功。
          posted @ 2009-03-27 14:25 張永耀 閱讀(310) | 評(píng)論 (0)編輯 收藏

          用delphi和VB實(shí)現(xiàn)瀏覽器中超長(zhǎng)文件的上傳
           

          摘 要 本文通過(guò)delphi的Tihttp控件,將超大文件分割成幾個(gè)小文件,通過(guò)構(gòu)造的表單數(shù)據(jù)流,

                      直接發(fā)送到接收數(shù)據(jù)網(wǎng)頁(yè),由vb編寫(xiě)的服務(wù)器端進(jìn)行文件接收和還原

          一、問(wèn)題的提出:

          本單位在開(kāi)發(fā)課件生成系統(tǒng)時(shí),需要通過(guò)瀏覽器向服務(wù)器指定目錄傳送大的音、視頻文件。在微軟asp中未提供相應(yīng)的控件,asp.net雖然提供了form表單中的file控件進(jìn)行文件上傳,但對(duì)上傳的文件有長(zhǎng)度限制,文件長(zhǎng)度大于50M上傳會(huì)失敗,而微軟基于安全考量,file控件中的文件名在運(yùn)行期間只讀,這樣利用微軟提供的控件向服務(wù)器端上傳長(zhǎng)度超過(guò)50M的文件變?yōu)椴豢尚校仨毩砼鑿健?/span>

          二、解決方案

          delphi以其強(qiáng)大的控件集,快速的RAD開(kāi)發(fā),深得程序開(kāi)發(fā)人員的青睞,其最新控件集Indy,集成了大部分流行的Internet協(xié)議,包括TCPUDPDNSICMPFINGERFTPGOPHERHTTPPOP3SMTPTELNETWHOIS,而瀏覽器的傳輸協(xié)議為http。這樣我們可以利用delphi7中的TIHTTP控件,將數(shù)據(jù)打包后上傳到服務(wù)器端。基本思路為:開(kāi)發(fā)兩部分功能程序,一個(gè)為ActiveX控件,嵌入到網(wǎng)頁(yè)中,負(fù)責(zé)將客戶(hù)端本地上傳文件分解成n個(gè)數(shù)據(jù)包,每個(gè)數(shù)據(jù)包直接編碼成“multipart/form-data”格式的表單信息,依次調(diào)用TIhttp控件的post方法向服務(wù)器端發(fā)送信息。另一個(gè)為服務(wù)器端的com組件,接受發(fā)送過(guò)來(lái)的原始信息,將數(shù)據(jù)包拼接還原成文件保存到服務(wù)器的指定目錄中。

          三、技術(shù)要點(diǎn):

              1Delyhi 7開(kāi)發(fā)Active X控件要點(diǎn):選擇新建項(xiàng)目→Active x標(biāo)簽→Active Form→填入控件名可快速搭建一個(gè)Acfire X控件架構(gòu),產(chǎn)生一個(gè)表單和一個(gè)框架代碼文件。

          2.上傳Active x控件設(shè)計(jì)要點(diǎn):①表單控件中放置一個(gè)編輯控件、三個(gè)命令按鈕、一個(gè)進(jìn)度條控件、一個(gè)文本標(biāo)簽控件、一個(gè)文件對(duì)話框控件。編輯控件用來(lái)放置上傳文件名。一個(gè)瀏覽按鈕打開(kāi)文件選擇對(duì)話框,選擇上傳文件;進(jìn)度條控件顯示上傳文件進(jìn)度;文本標(biāo)簽顯示上傳文件百分比,取消按鈕可中斷文件上傳。

          ②項(xiàng)目包含兩個(gè)代碼文件,其中一個(gè)文件用來(lái)將上傳文件拆分成小數(shù)據(jù)包。其關(guān)鍵代碼如下:

              for y:=0 to filenum  do

                 begin

                   if y=0  then   //第一個(gè)包

                       begin

                      if y <> filenum then

                            begin

                                for i:=1 to basenum do

                                  begin

                                     read(f,ch);

                                     tempf:=chr(ch);

                                     temp:=temp+tempf;

                                    application.ProcessMessages;

                                  end;

                              vflag:=postdata(vurl,vfilename,temp,'0');

                              end

                            else

                                   begin

                                   j:=0;

                                      while not eof(f) do

                                      begin

                                        read(f,ch);

                                      tempf:=chr(ch);

                                      temp:=temp+tempf;

                                      j:=j+1;

                                      application.ProcessMessages;

                            vflag:=postdata(vurl,vfilename,temp,'-2');

                          end;

                         end

                         else if y<> filenum then //中間包

                             begin

                                for i:=1 to basenum do

                                  begin

                                     read(f,ch);

                                    tempf:=chr(ch);

                                     temp:=temp+tempf;

                                      application.ProcessMessages;

                                  end;

                                    vflag:=postdata(vurl,vfilename,temp,'1');

                            end

                         else  //最后一個(gè)包

                           begin

                                  j:=0;

                                  while not eof(f) do

                                 begin

                                   read(f,ch);

                                   tempf:=chr(ch);

                                   temp:=temp+tempf;

                                   j:=j+1;

                                    application.ProcessMessages;

                               end;

                             vflag:=postdata(vurl,vfilename,temp,'-1');

                           end;

                 end;

          end;

          ③另一個(gè)文件用來(lái)將小數(shù)據(jù)包按照http格式封裝成二進(jìn)制文件上傳數(shù)據(jù)流發(fā)送到指定的接收頁(yè)面(URL),數(shù)據(jù)流除必要的頭信息,包含兩個(gè)表單城,一個(gè)數(shù)據(jù)塊,其中一個(gè)表單域用來(lái)傳遞文件標(biāo)記,用來(lái)區(qū)分本數(shù)據(jù)包是第一個(gè)包,中間包還是最后一個(gè)包,另一個(gè)表單域傳遞上傳文件名,其關(guān)鍵代碼如下:

             try

               filedata.Seek(0,sofrombeginning);

               tempstring:='';

               tempstring:=tempstring+'------------------------------7cf87224d2020a'+

                   newline;

               tempstring:=tempstring+'Content-Disposition: form-data;name="vflag"'+newline;

               tempstring:=tempstring+''+newline;

               tempstring:=tempstring+vflag+newline;

               tempstring:=tempstring+''+newline;

               tempstring:=tempstring+''+newline;

               tempstring:=tempstring+'Content-Disposition: form-data; name="editfilename"; filename="'+infile+'"'+newline;

               tempstring:=tempstring+'Content-Type: application/octet-stream'+newline;

               tempstring:=tempstring+''+newline;

               fillchar(temparray,sizeof(temparray),#0);

               strpcopy(temparray,tempstring);

               request.Write(temparray,length(tempstring));

               request.seek(0,sofromend);

               request.CopyFrom(filedata,filedata.size);

               tempstring:='';

               tempstring:=tempstring+''+newline;

               tempstring:=tempstring+'------------------------------7cf87224d2020a--'

                    +newline;

               fillchar(temparray,sizeof(temparray),#0);

               strpcopy(temparray,tempstring);

               request.write(temparray,length(tempstring));

               try

                 http.Post(url,request,response);

                 if pos('成功',response.datastring)<>0 then

                    flag:=1

               end.

          End.

          ④本ActiveX控件特色:可以實(shí)時(shí)顯示上傳進(jìn)度,并能隨時(shí)中斷文件的上傳,上傳頁(yè)面畫(huà)面如圖所示,可不能隨時(shí)中斷文件上傳,即應(yīng)用程序能隨時(shí)從循環(huán)語(yǔ)句中跳出,在循環(huán)語(yǔ)句中使用了ayydicdition Process Messages語(yǔ)句,該語(yǔ)句用來(lái)監(jiān)聽(tīng)和處理系統(tǒng)消息這樣就有效避免了文件上傳時(shí),不能進(jìn)行系統(tǒng)的其它操作。

          3.用VB6.0開(kāi)發(fā)服務(wù)器端接收文件的Activeex dll,主要利用VB6.0強(qiáng)大的網(wǎng)頁(yè)操作功能,引用庫(kù)文件microsoft Active sever Page object library。其中包含有asp對(duì)象Asp library request。創(chuàng)建一個(gè)接收函數(shù)load,使用request對(duì)象讀取上傳給接收頁(yè)面的二進(jìn)制數(shù)據(jù)流,分離出上傳標(biāo)志、上傳文件名以及文件內(nèi)容,根據(jù)上傳標(biāo)志將分段傳送來(lái)的文件內(nèi)容拼接成一個(gè)完整的文件,保存到指定目錄。

          四、幾點(diǎn)說(shuō)明

              1.本程序在操作系統(tǒng)為Win98 Win2000的客戶(hù)端機(jī)器,IIS服務(wù)器端為Win 2000的環(huán)境下調(diào)試通過(guò);

          2.將upfile.htmupload.aspmyget.dllupfileproj1.ocx文件放置到IIS服務(wù)之虛擬目錄upfile下(缺省目錄為C:"Inetpub"unnroot"upfile);

          3.修改upfile.htmcodebase屬性(缺省為http://11.68.17.80/upfile/upfileproj1.ocx)中的IP地址為服務(wù)器端地址;

          4.修改delphi工程文件upfileprojl中的upfilelmpl1文件中的Button2 click事件中的vulstring=’http://11.68.17.80/upfile/upload.asp’一行數(shù)據(jù),將其中的IP地址轉(zhuǎn)接為服務(wù)器端地址,重新編譯后將upfrleprojl.ocx放置到虛擬目錄下;

          5.上傳文件在服務(wù)器端的默認(rèn)保存目錄為c:"temp;

          6.須手工注冊(cè)myget.dll,命令語(yǔ)句為regsvr32  C:"inetpub"wwwroot"upfile"myget.dll

          7.覽器中敲擊網(wǎng)站地址執(zhí)行,缺省地址為http://11.68.17.80/upfile/upfile.htm
          posted @ 2009-03-27 08:48 張永耀 閱讀(490) | 評(píng)論 (0)編輯 收藏

          我們的產(chǎn)品中間件的啟動(dòng)是由批處理文件開(kāi)始,這就導(dǎo)致,始終有個(gè)DOS窗口,來(lái)顯示服務(wù)器的運(yùn)行情況。可客戶(hù)不樂(lè)意啊:他們就想萬(wàn)一誰(shuí)不小心把那窗口給關(guān)了,損害了數(shù)據(jù),那問(wèn)題可就大了!這個(gè)問(wèn)題確實(shí)是挺有價(jià)值的。
          首先,我們考慮WINDOWS環(huán)境吧,我不認(rèn)為WINDOWS環(huán)境下和*NIX環(huán)境下的實(shí)現(xiàn)有很大差別。想到以前看到的,聽(tīng)到的,再加上自己的經(jīng)驗(yàn),大概有這么集中方式:
        1. 包裝bat文件為exe文件,然后以后臺(tái)服務(wù)的形式注冊(cè)
        2. 利用windows自帶的Wscript.Shell
        3. 寫(xiě)個(gè)Swing界面小程序,利用多線程,啟動(dòng)應(yīng)用服務(wù),把DOS窗口替換成應(yīng)用窗口。
        4. 但我們需要考慮另外一點(diǎn):我們的應(yīng)用在運(yùn)行的時(shí)候,會(huì)向dos窗口輸出一些出來(lái)的一些信息,這些信息在很多情況下都是很有用的。現(xiàn)在如果把DOS窗口隱藏了,那么那些信息我把他們存放到哪兒呢?我想最好還是以文件的形式保存起來(lái),將來(lái)如有問(wèn)題還可以追查!
          現(xiàn)在考慮各種實(shí)現(xiàn)方式。包裝為exe的形式,也只能在windows環(huán)境下運(yùn)行,并且需要額外的工具;Swing界面小程序這個(gè)其實(shí)是最可行的,但我這個(gè)人比較懶,比較討厭寫(xiě)界面;利用windows自帶的Wscript.Shell,自然也只能依賴(lài)于windows環(huán)境,后來(lái)我想了下,其實(shí)這個(gè)方案可以和swing界面那個(gè)方案有不少東西是可以公用的。最后決定,為了簡(jiǎn)單期間,偶就先用Wscript.Shell,來(lái)做測(cè)試了。
          實(shí)際的情況大致是:
        5. 應(yīng)用服務(wù)的啟動(dòng)腳本是/startup.bat 實(shí)際中我們可以使用vbs腳本:
        6. dim ws
          Set ws = CreateObject("Wscript.Shell")
          ws.run "cmd /c /startup.bat >> myServer.log" ,vbhide
          通過(guò)這樣簡(jiǎn)單的設(shè)置,我們可以做到隱藏DOS窗口,但是,如果我們的應(yīng)用一下子運(yùn)行好幾個(gè)月,那我們的日志文件myServer.log的日積月累地,就太大了。我們?cè)诓檎覇?wèn)題的時(shí)候,也很不容易!所以我們應(yīng)該想法子把日志文件myServer.log,按時(shí)間或者按大小分開(kāi)存儲(chǔ)。這也是我們應(yīng)用服務(wù)器日志的做法。所以,我們需要再做一步中間處理,想想看"appRoot/startup.bat"這一步,我們?cè)诔绦虍?dāng)中還是可以獲得它的輸出結(jié)果的。看下面java程序:
          package nc.client.StartupUtil;

          import java.lang.ProcessBuilder;
          import java.util.Vector ;
          import java.io.BufferedReader;
          import java.io.File;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.io.FileWriter;
          import java.io.BufferedWriter;
          import java.util.Collections ;

          public class NC50StartUtil
          {

          public static final String logFileNamePrefix = "ncconsolelogs";

          public static void main(String[] args)
          {
          ProcessBuilder processBuilder = new ProcessBuilder("cmd", "/C", args[0]+"/startup.bat");
          processBuilder.directory(new File(args[0]));
          Process process = null;
          try
          {
          process = processBuilder.start();
          BufferedReader datais =
          new BufferedReader(
          new InputStreamReader( process.getInputStream()));


          // 服務(wù)器日志目錄
          String serverLogDirName = args[0] + "/nclogs/server";
          File serverLogDir = new File (serverLogDirName);
          if (!serverLogDir.exists())
          {
          serverLogDir.mkdirs();
          }

          int maxFileIndex = getMaxFileIndex(serverLogDirName).intValue();
          File logFile = new File(serverLogDirName+"/ncconsolelogs.log");
          if (!logFile.exists())
          {
          logFile.createNewFile();
          }
          else
          {
          // 如果已經(jīng)存在日志文件,則先把原來(lái)的文件歸檔,然后新創(chuàng)建一個(gè)日志文件
          StringBuffer oldFileName = new StringBuffer();
          oldFileName.append(serverLogDirName);
          oldFileName.append("/");
          oldFileName.append(logFileNamePrefix).append("[").append(maxFileIndex).append("].log");
          logFile.renameTo(new File(oldFileName.toString()));
          maxFileIndex++;
          //創(chuàng)建新的日志文件
          if (!logFile.exists())
          {
          logFile.createNewFile();
          }

          }

          BufferedWriter writer = new BufferedWriter(new FileWriter(logFile));

          // 文件的最大大小是2M
          int maxlength = 1024*1024*2;

          String c;
          while ((c = datais.readLine()) != null)
          {

          writer.write(c);
          writer.newLine();
          writer.flush();

          // 超過(guò)日志文件規(guī)定的大小了,則把日志文件歸檔,然后新創(chuàng)建一個(gè)日志文件
          if (logFile.length() > maxlength)
          {
          writer.close();
          StringBuffer oldFileName = new StringBuffer();
          oldFileName.append(serverLogDirName);
          oldFileName.append("/");
          oldFileName.append(logFileNamePrefix).append("[").append(maxFileIndex).append("].log");
          logFile.renameTo(new File(oldFileName.toString()));
          maxFileIndex++;

          // 創(chuàng)建新的日志文件
          if (!logFile.exists())
          {
          logFile.createNewFile();
          }
          writer =   new BufferedWriter(new FileWriter(logFile));
          }

          }
          }
          catch(IOException e)
          {
          e.printStackTrace ();
          }
          }

          public static Integer getMaxFileIndex(String ncconsolelogdirname)
          {
          File ncconsolelogdir = new File(ncconsolelogdirname);
          File[] ncconsolelogs = ncconsolelogdir.listFiles(new NcLogFileNameFilter(logFileNamePrefix));

          if (ncconsolelogs != null && ncconsolelogs.length > 0)
          {
          Vector v = new Vector();
          for (int i=0, len=ncconsolelogs.length; i startIndex)
          {
          String index = logFileName.substring (startIndex+1, endIndex);
          int ind = -1;
          try
          {
          ind = Integer.parseInt(index);
          }
          catch(Exception e)
          {

          }

          if (ind > 0)
          {
          v.add(ind);
          }
          }
          }
          if (v.size() > 0)
          {
          return Collections.max(v) + 1;
          }
          else
          {
          return 1;
          }
          }

          return 1;
          }
          }
          package nc.client.StartupUtil;

          import java.io.File;
          import java.io.FilenameFilter;

          // 一個(gè)簡(jiǎn)單的文件名過(guò)濾類(lèi)
          public class NcLogFileNameFilter implements FilenameFilter {

          private String fileNamePrefix = null;

          public NcLogFileNameFilter(String fileNamePrefix)
          {
          this.fileNamePrefix = fileNamePrefix;
          }

          public boolean accept(File dir, String name)
          {
          if (name.toLowerCase().startsWith(fileNamePrefix))
          {
          return true;
          }
          return false;
          }
          }
          之后,為了運(yùn)行方便,我們把這兩個(gè)類(lèi)編譯后打成可執(zhí)行的jar包,例如ncstartuputil.jar。并修改vbs腳本為:
          dim ws
          Set ws = CreateObject("Wscript.Shell")
          ws.run "cmd /c java -jar ncstartuputil.jar E:/nchome_zhengshi" ,vbhide
          如果換做swing界面,其實(shí)僅僅需要寫(xiě)另外一個(gè)Thread,thread的主體也正式上面static main方法主體,然后通過(guò)多線程,可以獲得原始start.bat批處理文件的輸出,并且把輸出的信息放到一個(gè)textarea里面顯示出來(lái)。:-)....
          posted @ 2009-03-26 17:16 張永耀 閱讀(740) | 評(píng)論 (0)編輯 收藏

          最近做在做一個(gè)項(xiàng)目,涉及到文件上傳的問(wèn)題。 以前也做過(guò)文件上傳。但都是些小文件,不超過(guò)2M。 這次要求上傳1G以上的東西。 沒(méi)辦法找來(lái)資料研究了一下。 基于WEB的文件上傳可以使用FTP和HTTP兩種協(xié)議,用FTP的話雖然傳輸穩(wěn)定,但安全性是個(gè)嚴(yán)重的問(wèn)題,所以沒(méi)有考慮。 剩下只有HTTP。 在HTTP中有3種方式,PUT、WEBDAV、RFC1867,前2種方法不適合大文件上傳,在這里也不說(shuō)了。
          確定使用RFC1867格式處理之后開(kāi)始分析流行的上傳組件。看了N多代碼之后發(fā)現(xiàn),目前無(wú)組件程序和一些COM組件都是使用Request.BinaryRead方法。一次性得到上傳的數(shù)據(jù),然后分析處理。這就是為什么上傳大文件很慢的原因了,IIS超時(shí)不說(shuō),就算1G文件上去了,分析處理也得一陣子。 之后我把注意力放在國(guó)外商業(yè)組件上,比較流行的有Power-Web,AspUpload,ActiveFile,ABCUpload,aspSmartUpload,SA-FileUp。其中比較優(yōu)秀的是ASPUPLOAD和SA-FILE,他們號(hào)稱(chēng)可以處理2G的文件(SA-FILE EE版甚至沒(méi)有文件大小的限制),而且效率也是非常棒,難道編程語(yǔ)言的效率差這么多?(我的編程環(huán)境是VB6) 查了一些資料,覺(jué)得他們都是直接操作文件流。這樣就不受文件大小的制約。 真是個(gè)好方法。
          但老外的東西也不是絕對(duì)完美,ASPUPLOAD處理大文件后,內(nèi)存占用情況驚人。1G左右都是稀松平常。我用的是3.0.0.3版。至于SA-FILE雖然是好東西但是破解難尋(郁悶死..) 失望之際,發(fā)現(xiàn)2款上傳組件,Lion.Web.UpLoadModule和AspnetUpload,都是.NET的,估計(jì)也是操作文件流。但是上傳速度和CPU占用率都不如老外的商業(yè)組件。
          做了個(gè)測(cè)試,LAN內(nèi)傳1G的文件。ASPUPLOAD上傳速度平均是4.4M/s,CPU占用10-15,內(nèi)存占用700M。SA-FILE也差不多這樣。而AspnetUpload最快也只有1.5M/s,平均是700K/s,CPU占用15-39,測(cè)試環(huán)境:PIII800,256M內(nèi)存,100M LAN。我想AspnetUpload速度慢是可能因?yàn)橐贿吔邮瘴募贿厡?xiě)硬盤(pán)。資源占用低的代價(jià)就是降低傳輸速度。 但也不得不佩服老外的程序,CPU占用如此之低.....這樣2個(gè).net的組件也被PASS.

          稍帶2個(gè)問(wèn)題就是上傳進(jìn)度和斷點(diǎn)續(xù)傳。
          顯示上傳進(jìn)度比較簡(jiǎn)單,主要是查詢(xún)用戶(hù)上傳的狀態(tài),用Script顯示到瀏覽器中,至于無(wú)刷新顯示就要看腳本語(yǔ)言運(yùn)用的熟練程度了。
          斷點(diǎn)續(xù)傳,HTTP方式是實(shí)現(xiàn)不了的,因?yàn)闉g覽器每次上傳文件都是從頭開(kāi)始,沒(méi)有Range標(biāo)簽。實(shí)現(xiàn)的方法只能用ActiveX。

          研究之后決定寫(xiě)個(gè)CGI來(lái)處理文件上傳。 這樣可以不走IIS以免程序出錯(cuò)影響網(wǎng)站訪問(wèn)。小弟比較菜只能用VB6做,完成之后發(fā)現(xiàn)WIN CGI的效率簡(jiǎn)直就是差的不能再差。索性寫(xiě)個(gè)FILE SERVER,專(zhuān)門(mén)處理文件的上傳。但是現(xiàn)在遇到一個(gè)2個(gè)問(wèn)題。
          一、用WINSOCK控件接收到的文本有亂碼 不知道是程序轉(zhuǎn)換時(shí)的錯(cuò)誤還是WINSOCK本身垃圾,SO 換了PowerTCP的WINSOCK TOOL,情況有所好轉(zhuǎn) 亂碼沒(méi)那么多了.........準(zhǔn)備換vb.net,直接操作socket,程序還沒(méi)做,不知道用.net接收會(huì)不會(huì)亂碼。再有就哭了。
          二、這個(gè)問(wèn)題就比較初級(jí)了....接收到的文件流不能還原成文件..寒一個(gè),

          最后就是如何高效處理文件流, 我想來(lái)想去也就只有2種方法,一是都放在內(nèi)存里,然后一起處理, 二是一邊接收一邊寫(xiě)文件。 但這2種方法都不盡如人意思
          posted @ 2009-03-26 17:00 張永耀 閱讀(126) | 評(píng)論 (0)編輯 收藏


          http://cydn.8k.com      http://cydn.8m.com     http://cydn.s5.com

          登陸修改地址:http://cydn.8k.com/cgi-bin/login

          http://cydn.8k.com/cgi-bin/login

          http://cydn.s5.com/cgi-bin/login


          1。  個(gè)人空間和Blog   http://zhoubing518.x.27h.org/

          也就是: http://www.27h.com/blog/html/03/143103.html

          支持Ftp上傳,地址:ftp.27h.com  最好用CutFtp工具上傳。用戶(hù)名密碼為登陸的用戶(hù)名和密碼

          支持Html解析,不能解析jsp,屬于WEB服務(wù)器。

          網(wǎng)站的信件內(nèi)容如下:

               尊敬的 cydn 用戶(hù)你好!
              我是醬子家園的管理員!
          感謝您申請(qǐng)我們的免費(fèi)主頁(yè)服務(wù),您已經(jīng)成為我們的用戶(hù)。
          ======================================================================
          您的FTP地址為 ftp://ftp.27h.com
          用戶(hù)名為 cydn
          目前空間大小為 50M 您的主頁(yè)地址為 http://cydn.27h.com

          您必須安裝FTP軟件,例如LEAPFTP CUTEFTP等

          2.    速度最快,最穩(wěn)定的一個(gè):  http://hi.baidu.com/zbzb  

          不能上傳自己的Html頁(yè)面.但有100M的照片庫(kù)  

          3.   個(gè)人空間   http://zb.s5.com    國(guó)外免費(fèi)空間,支持Html .用戶(hù)登陸頁(yè):http://www.s5.comhttp://www.s5.comhttp://www.s5.comhttp://www.s5.com    國(guó)外免費(fèi)空間,支持Html .用戶(hù)登陸頁(yè):http://www.s5.com

          登陸修改地址:http://zb.s5.com/cgi-bin/login

          4.   個(gè)人Blog  博客地址:http://zb66.139.com   您的用戶(hù)名:zb66  您的密碼:***
          手機(jī)登陸的WAP地址:http://zb66.m.139.com     頁(yè)面不是很好看,模版少。速度快,.net網(wǎng)站。

          5.  http://host.tomore.com   

          主機(jī)名:http://host.tomore.com/cydn/

          FTP:

          主機(jī):host.tomore.com
          用戶(hù)名:cydn
          密碼:你的會(huì)員密碼.
          空間大小:50 M .

          Mysql:未開(kāi)通,請(qǐng)升級(jí)為正式會(huì)員!

          5.  我申請(qǐng)的幾個(gè)免費(fèi)域名

          我申請(qǐng)的域名:
          http://cydn.wyou.cn
          http://smys.9126.com
          http://smys.9126.com
          http://cydn.1www.cn/http://xacydn.9126.com
          圣博個(gè)人免費(fèi)空間:
          http://cydn.home.sunbo.net

          6.  免費(fèi)域名申請(qǐng)網(wǎng)址簡(jiǎn)介:

          http://www.wyou.cn/reg/reg.asp   
          免費(fèi)域名服務(wù)由萬(wàn)游網(wǎng)提供

          http://www.xinfree.com/default.htm

          申請(qǐng)地址:http://www.008.net/free/

          申請(qǐng)網(wǎng)址:http://ew88.com/reg.asp

          申請(qǐng)地址:http://www.eee.cc/

          申請(qǐng)網(wǎng)址: http://www.chinese.cn.com/freedomain/
          CHINESE.cn.com 免費(fèi)域名開(kāi)始測(cè)試,域名長(zhǎng)度要求在3至20個(gè)字符之間。 您可以注冊(cè)以下域名:
          yourname.chinese.cn.com
          yourname.163.cn.com
          yourname.263.cn.com
          yourname.sina.cn.com
          yourname.sohu.cn.com
          yourname.tom.cn.com
          快來(lái)?yè)屪⒀剑?/p>

          申請(qǐng)網(wǎng)址: http://reg.900du.com/

          免費(fèi) ***.k6.cn域名!
          申請(qǐng)網(wǎng)址: http://jsyzt.k6.cn/reg/reg.asp

          申請(qǐng)網(wǎng)址:http://mycool.net/

          申請(qǐng)網(wǎng)址:http://my.k6.cn/reg/reg2.asp

          很不錯(cuò)的免費(fèi)域名,共27種后綴,例如:cc.ly/tv.ly/cn.ly/on.ly,快去申請(qǐng)吧!

          申請(qǐng)網(wǎng)址:
          http://tv.ly/

          可選擇的后綴有:   hk.ly   dj.md   ok.mu   n.md   w.md   hk.md   tea.ms   email.ly   cn.ly   jp.ly   kr.pn   cc.ly   tv.ly   co.kr.mw   co.kr.pn   name.md   kr.mw   to.tc   email.dj   blog.vg   on.ly   cc.la   cn.la   tw.la   jp4.jp   na.la   wa.la

          Lycos中國(guó)免費(fèi)聊天室申請(qǐng)! 
          時(shí)間: 2004-07-12 21:08:37 | [<<] [>>]
          --------------------------------------------------------------------------------
              免費(fèi)提供個(gè)人聊天室,申請(qǐng)簡(jiǎn)單,只需在主頁(yè)添加一段html代碼即可,沒(méi)有廣告,速度尚可,但功能較少。

          申請(qǐng)網(wǎng)址: http://chat.lycos.com.cn/hkcn/code.html
          碧聊免費(fèi)聊天室申請(qǐng)!
          --------------------------------------------------------------------------------
          免費(fèi)提供支持10人的語(yǔ)音聊天室,速度快、功能強(qiáng),如果需要更大在線人數(shù)可以購(gòu)買(mǎi)收費(fèi)服務(wù)。

          申請(qǐng)網(wǎng)址: http://www.bliao.com/help/help23.htm

          posted @ 2009-03-26 14:12 張永耀 閱讀(116) | 評(píng)論 (0)編輯 收藏

          閱讀全文
          類(lèi)別:數(shù)據(jù)庫(kù) 查看評(píng)論
          文章來(lái)源:http://hi.baidu.com/zbzb/blog/item/286f8b5438a4bf183b293556.html
          posted @ 2009-03-26 13:21 張永耀 閱讀(51) | 評(píng)論 (0)編輯 收藏

          閱讀全文
          類(lèi)別:免費(fèi)資源 查看評(píng)論
          文章來(lái)源:http://hi.baidu.com/zbzb/blog/item/ef6dae7724dae11cb151b9d4.html
          posted @ 2009-03-26 13:21 張永耀 閱讀(64) | 評(píng)論 (0)編輯 收藏

          閱讀全文
          類(lèi)別:底層軟件 查看評(píng)論
          文章來(lái)源:http://hi.baidu.com/zbzb/blog/item/9013d0ca2ad45241f31fe763.html
          posted @ 2009-03-26 13:21 張永耀 閱讀(88) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題
          共3頁(yè): 上一頁(yè) 1 2 3 下一頁(yè) 
          主站蜘蛛池模板: 株洲县| 河间市| 柳江县| 马鞍山市| 四平市| 拜城县| 缙云县| 通江县| 马鞍山市| 北京市| 木兰县| 颍上县| 舒兰市| 凤台县| 额济纳旗| 平度市| 板桥市| 布尔津县| 朝阳区| 建昌县| 天柱县| 朝阳县| 阜南县| 封开县| 诏安县| 舟曲县| 九台市| 怀远县| 万载县| 同心县| 珲春市| 乐山市| 科尔| 双桥区| 兴义市| 来凤县| 雅安市| 贞丰县| 灵璧县| 北京市| 江门市|