共享物件

Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本

共享物件有時候又稱為「Flash cookie」,是一種由您所瀏覽網站在您的電腦上建立的資料檔案。共享物件最常用來增強您的網路瀏覽體驗,例如,讓您自訂經常瀏覽的網站外觀。

關於共享物件

共享物件的作用與瀏覽器 cookie 類似。SharedObject 類別可用來將資料儲存在使用者的本機硬碟上,並在相同的工作階段或後面的工作階段期間呼叫該資料。應用程式只有在相同的網域上執行時,才能存取它們自己的 SharedObject 資料。資料不會傳送至伺服器,且無法由在其他網域中執行的其他應用程式存取,但可供相同網域的應用程式存取。

共享物件與 cookie 的比較

cookie 和共享物件十分類似。因為大部分網頁程式設計人員都熟悉 cookie 的運作,所以將本機 SharedObject 與 cookie 做比較可能比較有用。

遵守 RFC 2109 標準的 cookie 一般具有下列屬性:

  • 它們會過期,而且預設通常是在工作階段結束時。

  • 用戶端可以根據特定網站來停用它們。

  • 總限制為 300 個 cookie,而每個網站最多 20 個 cookie。

  • 個別的大小通常限制為 4 KB。

  • 它們有時被認為是安全性威脅,因此有時會在用戶端上予以停用。

  • 它們儲存在用戶端瀏覽器所指定的位置。

  • 它們是透過 HTTP 從用戶端傳輸至伺服器。

    相較之下,共享物件具有下列屬性:

  • 它們預設不會過期。

  • 每個的大小預設都限制為 100 KB。

  • 它們可以儲存簡單資料類型 (例如 String、Array 和 Date)。

  • 它們儲存在應用程式所指定的位置 (在使用者的主目錄中)。

  • 它們不會在用戶端與伺服器之間進行傳輸。

關於 SharedObject 類別

使用 SharedObject 類別,您可以建立和刪除共享物件,以及偵測所使用之 SharedObject 物件的目前大小。SharedObject 類別包含下列方法。

方法

說明

clear()

清除 SharedObject 物件中的所有資料,以及刪除磁碟中的 SharedObject 檔案。

flush()

立即將 SharedObject 檔案寫入用戶端上的檔案。

getLocal()

傳回用戶端的網域特定本機 SharedObject 物件的參考。如果沒有,則此方法會在用戶端上建立新的共享物件。

getSize()

取得 SharedObject 檔案的大小 (以位元組為單位)。預設大小限制是 100 KB,但如果用戶端允許,還可以更大。

除了這些方法之外,SharedObject 物件還具有下列屬性:

屬性

說明

data

唯讀屬性,代表共享物件所儲存的特質集合。

onStatus

共享物件的事件處理常式,是針對每個警告、錯誤或資訊備註所叫用。

建立共享物件

若要建立 SharedObject 物件,請使用 SharedObject.getLocal() 方法,其語法如下:

SharedObject.getLocal("objectName" [, pathname]): SharedObject

下列範例會建立稱為 mySO 的共享物件:

public var mySO:SharedObject; 
mySO = SharedObject.getLocal("preferences");

這樣會在用戶端電腦上建立稱為 preferences.sol 的檔案。

「本機」這個詞彙指的是共享物件的位置。在此例中,Adobe® Flash® Player 會在用戶端本機的主目錄中儲存 SharedObject 檔案。

當您建立共享物件時,Flash Player 會在其執行程序內建立應用程式及網域的新目錄。也會建立 *.sol 檔案,以儲存 SharedObject 資料。此檔案的預設位置是使用者主目錄的子目錄。下表顯示此目錄的預設位置:

作業系統

位置

Windows 95/98/ME/2000/XP

c:/Documents and Settings/username/Application Data/Macromedia/Flash Player/#SharedObjects

Windows Vista

c:/Users/username/AppData/Roaming/Macromedia/Flash Player/#SharedObjects

Macintosh OS X

/Users/username/Library/Preferences/Macromedia/Flash Player/#SharedObjects/web_domain/path_to_application/application_name/object_name.sol

Linux/Unix

/home/username/.macromedia/Flash_Player/#SharedObjects/web_domain/path_to_application/application_name/object_name.sol

#SharedObjects 目錄下是隨機命名的目錄。該目錄下是符合主機名稱的目錄,然後是應用程式的路徑,最後是 *.sol 檔案。

例如,如果您在本機主機上要求應用程式 MyApp.swf,而且位在子目錄 /sos 內,則 Flash Player 會將 *.sol 檔案儲存至下列位置 (在 Windows XP 上):

c:/Documents and Settings/fred/Application Data/Macromedia/Flash Player/#SharedObjects/KROKWXRK/#localhost/sos/MyApp.swf/data.sol
備註: 如果您未在 SharedObject.getLocal() 方法中提供名稱,則 Flash Player 會將檔案命名為 undefined.sol。

Flash 預設最多可為每個網域在本機儲存 100 KB 的持續性 SharedObject 物件。使用者可以設定此值。應用程式嘗試將資料儲存至會讓它大於 100 KB 的共享物件時,Flash Player 會顯示「本地儲存區」對話框,讓使用者可以針對要求存取的網域允許或拒絕更多本地儲存區。

指定路徑

您可以使用選用的 pathname 參數指定 SharedObject 檔案的位置。此檔案必須是該網域之 SharedObject 目錄的子目錄。例如,如果您在 localhost 上要求應用程式並指定下列項目:

mySO = SharedObject.getLocal("myObjectFile","/");

Flash Player 會將 SharedObject 檔案寫入 /#localhost 目錄 (如果應用程式離線,則為 /localhost)。這適用於您希望用戶端上的多個應用程式可以存取相同的共享物件時。在此情況下,用戶端可以執行兩個 Flex 應用程式,這兩個應用程式都會指定共享物件的路徑,即網域的根目錄;用戶端之後就可以從這兩個應用程式存取相同的共享物件。若要在多個應用程式之間共享資料而不加以保存,可以使用 LocalConnection 物件。

如果您指定的目錄不存在,Flash Player 就不會建立 SharedObject 檔案。

將資料新增至共享物件

您可以使用 SharedObject 物件的 data 屬性,將資料新增至 SharedObject 的 *.sol 檔案。若要將新的資料新增至共享物件,請使用下列語法:

sharedObject_name.data.variable = value;

下列範例會將 userNameitemNumbersadminPrivileges 屬性及其值新增至 SharedObject:

public var currentUserName:String = "Reiner"; 
public var itemsArray:Array = new Array(101,346,483); 
public var currentUserIsAdmin:Boolean = true; 
mySO.data.userName = currentUserName; 
mySO.data.itemNumbers = itemsArray; 
mySO.data.adminPrivileges = currentUserIsAdmin;

在您將值指定給 data 屬性之後,必須指示 Flash Player 將那些值寫入 SharedObject 的檔案。若要強制 Flash Player 將值寫入 SharedObject 的檔案,請使用 SharedObject.flush() 方法,如下所示:

mySO.flush();

如果您未呼叫 SharedObject.flush() 方法,則 Flash Player 會在應用程式結束時將值寫入檔案。不過,如果資料超出預設設定,使用者就無法增加 Flash Player 儲存資料的可用空間。因此,最佳做法是呼叫 SharedObject.flush()

在使用 flush() 方法將共享物件寫入使用者的硬碟時,您必須仔細檢查使用者是否已經使用「Flash Player 設定管理員」(www.macromedia.com/support/documentation/tw/flashplayer/help/settings_manager07.html) 明確停用本機儲存功能,如下列範例所示:

var so:SharedObject = SharedObject.getLocal("test"); 
trace("Current SharedObject size is " + so.size + " bytes."); 
so.flush();

在共享物件中儲存物件

您可以在 SharedObject 的 data 屬性中儲存簡單物件,例如 Arrays 或 Strings。

下列範例是 ActionScript 類別,可定義方法來控制與共享物件的互動。這些方法可讓使用者在共享物件中新增和移除物件。此類別會儲存內含簡單物件的 ArrayCollection。

package { 
    import mx.collections.ArrayCollection; 
    import flash.net.SharedObject; 
 
    public class LSOHandler { 
 
        private var mySO:SharedObject; 
        private var ac:ArrayCollection; 
        private var lsoType:String; 
 
        // The parameter is "feeds" or "sites". 
        public function LSOHandler(s:String) { 
            init(s); 
        } 
 
        private function init(s:String):void { 
            ac = new ArrayCollection(); 
            lsoType = s; 
            mySO = SharedObject.getLocal(lsoType); 
            if (getObjects()) { 
                ac = getObjects(); 
            } 
        } 
 
        public function getObjects():ArrayCollection { 
            return mySO.data[lsoType]; 
        } 
 
        public function addObject(o:Object):void { 
            ac.addItem(o); 
            updateSharedObjects(); 
        } 
 
        private function updateSharedObjects():void { 
            mySO.data[lsoType] = ac; 
            mySO.flush(); 
        } 
    } 
 
}

下列 Flex 應用程式會建立所需的每種共享物件類型的 ActionScript 類別實體。然後會在使用者新增或移除部落格或網站 URL 時,針對該類別呼叫方法。

<?xml version="1.0"?> 
<!-- lsos/BlogAggregator.mxml --> 
<mx:Application 
    xmlns:local="*" 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    creationComplete="initApp()" 
    backgroundColor="#ffffff" 
> 
    <mx:Script> 
        <![CDATA[ 
        import mx.collections.ArrayCollection; 
        import mx.utils.ObjectUtil; 
        import flash.net.SharedObject; 
 
        [Bindable] 
        public var welcomeMessage:String; 
        
        [Bindable] 
        public var localFeeds:ArrayCollection = new ArrayCollection(); 
 
        [Bindable] 
        public var localSites:ArrayCollection = new ArrayCollection(); 
 
        public var lsofeeds:LSOHandler; 
        public var lsosites:LSOHandler; 
 
        private function initApp():void { 
            lsofeeds = new LSOHandler("feeds"); 
            lsosites = new LSOHandler("sites"); 
            
            if (lsofeeds.getObjects()) { 
                localFeeds = lsofeeds.getObjects(); 
            } 
            if (lsosites.getObjects()) { 
                localSites = lsosites.getObjects(); 
            } 
        } 
        
        // Adds a new feed to the feeds DataGrid. 
        private function addFeed():void { 
            // Construct an object you want to store in the 
            // LSO. This object can contain any number of fields. 
            var o:Object = {name:ti1.text, url:ti2.text, date:new Date()}; 
            lsofeeds.addObject(o); 
    
            // Because the DataGrid's dataProvider property is 
            // bound to the ArrayCollection, Flex updates the 
            // DataGrid when you call this method. 
            localFeeds = lsofeeds.getObjects(); 
            
            // Clear the text fields. 
            ti1.text = '';        
            ti2.text = ''; 
        } 
        
        // Removes feeds from the feeds DataGrid. 
        private function removeFeed():void { 
            // Use a method of ArrayCollection to remove a feed. 
            // Because the DataGrid's dataProvider property is 
            // bound to the ArrayCollection, Flex updates the 
            // DataGrid when you call this method. You do not need 
            // to update it manually. 
            if (myFeedsGrid.selectedIndex > -1) { 
            
localFeeds.removeItemAt(myFeedsGrid.selectedIndex); 
             } 
        } 
        
        private function addSite():void { 
            var o:Object = {name:ti3.text, date:new Date()}; 
            lsosites.addObject(o); 
            localSites = lsosites.getObjects(); 
            ti3.text = '';                
        } 
        
        private function removeSite():void { 
            if (mySitesGrid.selectedIndex > -1) { 
            
localSites.removeItemAt(mySitesGrid.selectedIndex); 
            }       
        } 
 
        ]]> 
    </mx:Script> 
        
    <mx:Label text="Blog aggregator" fontSize="28"/> 
    
    <mx:Panel title="Blogs"> 
        <mx:Form id="blogForm"> 
            <mx:HBox> 
                <mx:FormItem label="Name:"> 
                    <mx:TextInput id="ti1" width="100"/> 
                </mx:FormItem> 
                <mx:FormItem label="Location:"> 
                    <mx:TextInput id="ti2" width="300"/> 
                </mx:FormItem> 
                <mx:Button id="b1" label="Add Feed" click="addFeed()"/> 
            </mx:HBox> 
 
            <mx:FormItem label="Existing Feeds:"> 
                <mx:DataGrid 
                    id="myFeedsGrid" 
                    dataProvider="{localFeeds}" 
                    width="400" 
                /> 
            </mx:FormItem> 
            <mx:Button id="b2" label="Remove Feed" click="removeFeed()"/> 
        </mx:Form> 
    </mx:Panel> 
    
    <mx:Panel title="Sites"> 
        <mx:Form id="siteForm"> 
            <mx:HBox> 
                <mx:FormItem label="Site:"> 
                    <mx:TextInput id="ti3" width="400"/> 
                </mx:FormItem> 
                <mx:Button id="b3" label="Add Site" click="addSite()"/> 
            </mx:HBox> 
 
            <mx:FormItem label="Existing Sites:"> 
                <mx:DataGrid 
                    id="mySitesGrid" 
                    dataProvider="{localSites}" 
                    width="400" 
                /> 
            </mx:FormItem> 
            <mx:Button id="b4" label="Remove Site" click="removeSite()"/> 
        </mx:Form> 
    </mx:Panel> 
    
</mx:Application>

在共享物件中儲存具有類型的物件

您可以在共享物件中儲存具有類型的 ActionScript 實體。作法是呼叫 flash.net.registerClassAlias() 方法來註冊類別。如果您建立類別的實體,並將它儲存於共享物件的資料成員中,之後再讀出該物件,便會取得具有類型的實體。SharedObject objectEncoding 屬性預設支援 AMF3 編碼,並且會從 SharedObject 物件解壓縮儲存的實體;儲存的實體會保留您在呼叫 registerClassAlias() 方法時指定的相同類型。

建立多個共享物件

您可以為相同 Flex 應用程式建立多個共享物件。若要執行這項作業,請為它們指定不同的實體名稱 (如下例所示):

public var mySO:SharedObject = SharedObject.getLocal("preferences"); 
public var mySO2:SharedObject = SharedObject.getLocal("history");

這樣會在 Flex 應用程式的本機目錄中建立 preferences.sol 檔案和 history.sol 檔案。

建立安全的 SharedObject

在使用 getLocal()getRemote() 建立本機或遠端 SharedObject 時,有一個選擇性的參數 secure 可以用來判斷是否僅限於透過 HTTPS 連線傳送的 SWF 檔才能存取此共享物件。如果此參數設定為 true,且 SWF 檔是透過 HTTPS 傳遞時,Flash Player 就會建立新的安全共享物件,或取得現有安全共享物件的參考;這個安全的共享物件就只能透過由 HTTPS 傳遞而呼叫 secure 參數設為 trueSharedObject.getLocal() 的 SWF 檔來讀取或寫入。如果此參數設定為 false 而 SWF 檔是透過 HTTPS 傳遞時,Flash Player 就會建立新的共享物件,或取得現有共享物件的參考。

這個共享物件可透過由非 HTTPS 連線傳遞之 SWF 檔來讀取或寫入。如果 SWF 檔是透過非 HTTPS 連線傳遞,而您嘗試將這個參數設為 true,則建立新的共享物件 (或存取之前建立的安全共享物件) 會失敗、擲回錯誤,並將共享物件設為 null。如果嘗試透過非 HTTPS 連線執行下列程式碼片段,SharedObject.getLocal() 方法將擲回錯誤:

try 
{ 
    var so:SharedObject = SharedObject.getLocal("contactManager", null, true); 
} 
catch (error:Error) 
{ 
    trace("Unable to create SharedObject."); 
}

不管參數的值為何,建立的共享物件數會依網域的允許磁碟空間總數而定。

顯示共享物件的內容

共享物件會將值儲存在 data 屬性內。您可以使用 for..in 迴圈在共享物件之內重複執行每一個值,如下列範例所示:

var so:SharedObject = SharedObject.getLocal("test"); 
so.data.hello = "world"; 
so.data.foo = "bar"; 
so.data.timezone = new Date().timezoneOffset; 
for (var i:String in so.data) 
{ 
    trace(i + ":\t" + so.data[i]); 
}

刪除共享物件

若要刪除用戶端上的 SharedObject,請使用 SharedObject.clear() 方法。這樣不會刪除應用程式共享物件預設路徑中的目錄。

下列範例會刪除用戶端中的 SharedObject 檔案:

public function destroySharedObject():void { 
    mySO.clear(); 
}

SharedObject 範例

下列範例顯示您可以將簡單物件 (例如 Date 物件) 儲存至 SharedObject 物件,而不需要手動序列化和還原序列化那些物件。

下列範例是以歡迎您第一次造訪開始。當您按一下「Log Out」時,應用程式會將目前日期儲存至共享物件中。下次啟動此應用程式或重新整理頁面時,應用程式會提醒您上次登出的時間,歡迎您再次使用。

若要查看作用中的應用程式,請啟動應用程式,按一下「Log Out」,然後重新整理頁面。此應用程式會顯示您在前次造訪時按一下「Log Out」按鈕的日期和時間。您隨時都可以按一下「Delete LSO」按鈕,以刪除儲存的資訊。

<?xml version="1.0"?> 
<!-- lsos/WelcomeMessage.mxml --> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initApp()"> 
  <mx:Script><![CDATA[ 
  public var mySO:SharedObject; 
  [Bindable] 
  public var welcomeMessage:String; 
 
  public function initApp():void { 
     mySO = SharedObject.getLocal("mydata"); 
     if (mySO.data.visitDate==null) { 
        welcomeMessage = "Hello first-timer!" 
     } else { 
        welcomeMessage = "Welcome back. You last visited on " + 
           getVisitDate(); 
     } 
  } 
 
  private function getVisitDate():Date { 
     return mySO.data.visitDate; 
  } 
 
  private function storeDate():void { 
     mySO.data.visitDate = new Date(); 
     mySO.flush(); 
  } 
  
  private function deleteLSO():void { 
     // Deletes the SharedObject from the client machine. 
     // Next time they log in, they will be a 'first-timer'. 
     mySO.clear(); 
  } 
  
  ]]></mx:Script> 
  <mx:Label id="label1" text="{welcomeMessage}"/> 
  <mx:Button label="Log Out" click="storeDate()"/> 
  <mx:Button label="Delete LSO" click="deleteLSO()"/> 
</mx:Application>