重要事項:本文件是在 2012 年之前撰寫,本文所述的驗證選項 (OAuth 1.0、AuthSub 和 ClientLogin) 已於 2012 年 4 月 20 日正式淘汰,因此無法再使用。建議您盡快改用 OAuth 2.0。
Google Sites Data API 可讓用戶端應用程式存取、發布及修改 Google 協作平台中的內容。 您的用戶端應用程式也可以要求近期活動清單、擷取修訂版本記錄,以及下載附件。
除了提供 Sites Data API 功能的相關背景資訊,本指南也提供使用 Java 用戶端程式庫與 API 互動的範例。如需設定用戶端程式庫的說明,請參閱開始使用 Google Data Java 用戶端程式庫。如要進一步瞭解 Java 用戶端程式庫使用的基礎通訊協定與傳統版協作平台 API 互動,請參閱通訊協定指南。
目標對象
本文件適用對象為想要使用 Google Data Java 用戶端程式庫編寫與 Google 協作平台互動的用戶端應用程式的開發人員。
開始使用
Google 協作平台會使用 Google 帳戶或 G Suite 帳戶進行驗證。如果您已擁有帳戶,就可以開始使用了。或者,您也可以建立新帳戶。
安裝程式庫
如需設定和安裝用戶端程式庫的相關說明,請參閱「開始使用 Google Data Java 用戶端程式庫」。如果您使用 Eclipse,該文章也會說明如何使用 Google Data API Eclipse 外掛程式設定專案。以下是開始使用前必須具備的條件:
- 安裝 Java 1.5 以上版本
- 下載用戶端程式庫 (
gdata-src.java.zip
的最新版本) - 下載依附元件清單
- 下載範例應用程式 (
gdata-samples.java.zip
的最新版本)
安裝 .jar 後,您需要在專案中加入以下內容:
java/lib/gdata-sites-2.0.jar
- 此處的 2.0 版適用於傳統 Sites API 的 1.4 版。java/lib/gdata-core-1.0.jar
java/lib/gdata-client-1.0.jar
java/lib/gdata-spreadsheet-3.0.jar
(如果使用清單頁面/清單項目)
此外,請務必加入依附元件 JAR (gdata-media-1.0.jar
、mail.jar
和 google-collect....jar
)。
執行範例應用程式
完整的應用程式範例位於 gdata-samples.java.zip
下載項目的 /java/sample/sites
子目錄中。您也可以透過「來源」分頁,在 SVN 存放區的 /trunk/java/sample/sites/ 中取得原始碼。SitesDemo.java
可讓使用者執行多項操作,說明如何使用傳統版 Sites API。
請注意,您必須加入 java/sample/util/lib/sample-util.jar
才能執行範例。
開始自己的專案
提示:請參閱搭配使用 Eclipse 與 Google Data API,瞭解如何快速設定 Eclipse 外掛程式。
視應用程式需求而定,您可能需要進行多項匯入作業。建議您從下列匯入作業開始:
import com.google.gdata.client.*; import com.google.gdata.client.sites.*; import com.google.gdata.data.*; import com.google.gdata.data.acl.*; import com.google.gdata.data.media.*; import com.google.gdata.data.sites.*; import com.google.gdata.data.spreadsheet.*; // If working with listpages / listitems import com.google.gdata.util.*;
接下來,您也需要設定 SitesService
物件,代表與傳統 Sites API 的用戶端連線:
SitesService client = new SitesService("yourCo-yourAppName-v1");
applicationName
引數應採用下列格式:company-applicationname-version
。這個參數是用於記錄。
注意:本指南的其餘部分假設您已在 client
變數中建立 SitesService
。
驗證傳統版協作平台 API
Java 用戶端程式庫可用於使用公開或私人動態饋給。視 Sites 權限和您要執行的作業而定,Sites Data API 會提供私人和公開動態消息的存取權。例如,您或許可以讀取公開網站的內容動態饋給,但無法進行更新,而這些內容需要經過驗證的用戶端。您可以透過 ClientLogin 使用者名稱/密碼驗證、AuthSub 或 OAuth 來完成這項操作。
如要進一步瞭解 AuthSub、OAuth 和 ClientLogin,請參閱 Google Data API 驗證總覽。
提示:API 支援安全資料傳輸層 (SSL) (HTTPS)。如果您使用 AuthSub/OAuth,請務必指定 https://sites.google.com/feeds/
的範圍,才能透過 SSL 要求動態消息。另請注意,對於 G Suite 網域,API 會遵循管理控制台中的「需要 SSL」設定。您可以呼叫 client.useSsl();
,強制所有 API 要求透過 HTTPS 傳送。
網頁應用程式的 AuthSub
需要驗證使用者 Google 帳戶的用戶端應用程式,應使用 AuthSub 網路應用程式驗證。操作員不需要存取 Google Sites 使用者的使用者名稱和密碼,只需要 AuthSub 權杖即可。
查看如何將 AuthSub 整合至網頁應用程式的操作說明
要求單次使用權杖
使用者首次造訪您的應用程式時,需要進行驗證。通常,開發人員會顯示一些文字和連結,引導使用者前往 AuthSub 核准頁面,以便驗證使用者並要求存取其文件。Google Data Java 用戶端程式庫提供產生這個網址的函式。下方程式碼會設定前往 AuthSubRequest 頁面的連結。
import com.google.gdata.client.*; String nextUrl = "http://www.example.com/welcome.jsp"; String scope = "https://sites.google.com/feeds/"; boolean secure = true; boolean session = true; String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);
如要驗證 G Suite 代管網域中的使用者,請按照下列步驟操作:
import com.google.gdata.client.*; String hostedDomain = "example.com"; String nextUrl = "http://www.example.com/welcome.jsp"; String scope = "https://sites.google.com/feeds/"; // SSL is also supported boolean secure = true; boolean session = true; String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);
getRequestUrl()
方法會採用多個參數 (對應至 AuthSubRequest 處理常式使用的查詢參數):
- next 網址:使用者登入帳戶並授予存取權後,Google 會將使用者重新導向至這個網址;上例中的
http://www.example.com/welcome.jsp
- 範圍 - 上例中的
https://sites.google.com/feeds/
- 布林值,用於指出權杖是否會在註冊模式下使用;上例中的
false
- 第二個布林值,用於指出符記是否會在稍後兌換成工作階段符記;上例中的
true
升級至工作階段權杖
請參閱「使用 AuthSub 和 Google Data API 用戶端程式庫」。
擷取工作階段符記的相關資訊
請參閱搭配使用 AuthSub 和 Google Data API 用戶端程式庫。
撤銷工作階段符記
適用於網路或已安裝/行動應用程式的 OAuth
OAuth 可做為 AuthSub 的替代方案,適用於網頁應用程式。OAuth 與 AuthSub 的安全與註冊模式類似,因為所有資料要求都必須經過數位簽署,而且您必須註冊網域。
查看將 OAuth 整合至已安裝的應用程式的操作說明
擷取要求權杖
請參閱「使用 OAuth 與 Google Data API 用戶端程式庫」。
授權要求權杖
請參閱「使用 OAuth 與 Google Data API 用戶端程式庫」。
升級為存取權杖
已安裝/行動應用程式的 ClientLogin
ClientLogin 應由需要對 Google 帳戶進行使用者驗證的已安裝或行動應用程式使用。首次執行時,應用程式會提示使用者輸入使用者名稱/密碼。後續要求則會參照驗證權杖。
查看將 ClientLogin 整合至已安裝應用程式的操作說明
如要使用 ClientLogin,請叫用 SitesService
物件的 setUserCredentials()
方法,該方法是從 GoogleService
繼承而來。指定代表您用戶端提出要求的使用者電子郵件地址和密碼。例如:
SitesService client = new SitesService("yourCo-yourAppName-v1"); client.setUserCredentials("example@gmail.com", "pa$$word");
提示:應用程式首次成功驗證使用者後,請將驗證權杖儲存在資料庫中,以便日後重用。因此每當應用程式執行時,都不必要求使用者提供密碼。詳情請參閱「撤銷授權權杖」。
如要進一步瞭解如何在 Java 應用程式中使用 ClientLogin,請參閱使用 ClientLogin 搭配 Google Data API 用戶端程式庫。
網站動態
網站動態饋給可用於列出使用者擁有或具備檢視權限的 Google 協作平台。也可以用來修改現有網站的名稱。如果是 G Suite 網域,也可以用來建立和/或複製整個網站。
列出網站
如要查詢網站動態饋給,請將 HTTP GET
傳送至網站動態饋給網址:
https://sites.google.com/feeds/site/site/
在 Java 用戶端中,您可以使用 SiteFeed
和 SiteEntry
類別來處理網站動態饋給:
public String getSiteFeedUrl() { String domain = "site"; // OR if the Site is hosted on G Suite, your domain (e.g. example.com) return "https://sites.google.com/feeds/site/" + domain + "/"; } public void getSiteFeed() throws IOException, ServiceException { SiteFeed siteFeed = client.getFeed(new URL(getSiteFeedUrl()), SiteFeed.class); for (SiteEntry entry : siteFeed.getEntries()){ System.out.println("title: " + entry.getTitle().getPlainText()); System.out.println("site name: " + entry.getSiteName().getValue()); System.out.println("theme: " + entry.getTheme().getValue()); System.out.println(""); } }
上述程式碼片段會列印網站的標題、網站名稱和網站主題。其他 getter 可用來存取動態饋給中的額外屬性。
建立新協作平台
注意:這項功能僅適用於 G Suite 網域。
如要佈建新網站,請建立新的 SiteEntry
,然後在網站動態饋給中呼叫客戶的 insert()
方法。
這個範例會使用主題「slate」(選用設定) 建立全新網站,並提供網站名稱 (必要) 和說明 (選用):
public String getSiteFeedUrl() { String domain = "example.com"; return "https://sites.google.com/feeds/site/" + domain + "/"; } public SiteEntry createSite(String title, String summary, String theme, String tag) throws MalformedURLException, IOException, ServiceException { SiteEntry entry = new SiteEntry(); entry.setTitle(new PlainTextConstruct(title)); entry.setSummary(new PlainTextConstruct(summary)); Theme tt = new Theme(); tt.setValue(theme); entry.setTheme(tt); entry.getCategories().add(new Category(TagCategory.Scheme.TAG, tag, null)); return client.insert(new URL(getSiteFeedUrl()), entry); } SiteEntry newSiteEntry = createSite("My Site Title", "summary for site", "slate", "tag");
上述要求會在 G Suite 網域 example.com
下建立新網站。因此,網站的網址會是 https://sites.google.com/a/example.com/my-site-title。
如果網站建立成功,伺服器會傳回 SiteEntry
物件,並填入伺服器新增的元素:網站連結、網站 ACL 動態消息的連結、網站名稱、標題、摘要等。
複製網站
注意:這項功能僅適用於 G Suite 網域。
複製網站的操作方式與建立新網站類似。不同之處在於您需要在新的 SiteEntry
上設定連結,其中包含要複製的網站自連結。以下範例說明如何複製「建立新網站」一節中建立的網站:
public SiteEntry copySite(String title, String summary, String sourceHref) throws MalformedURLException, IOException, ServiceException { SiteEntry entry = new SiteEntry(); entry.setTitle(new PlainTextConstruct(title)); entry.setSummary(new PlainTextConstruct(summary)); entry.addLink(SitesLink.Rel.SOURCE, Link.Type.ATOM, sourceHref); return client.insert(new URL(getSiteFeedUrl()), entry); } String sourceHref = newSiteEntry.getLink(SitesLink.Rel.SOURCE, Link.Type.ATOM).getHref(); SiteEntry myTwin = copySite("Duplicate Site", "A copy", sourceHref);
重要事項:
- 只能複製已驗證使用者擁有的網站和網站範本。
- 您也可以複製網站範本。如果在 Google Sites 設定頁面中勾選「將這個網站發布為範本」設定,該網站即為範本。
- 您可以從其他網域複製網站 (您必須是來源網站的擁有者)。
更新網站的中繼資料
如要重新命名網站、變更主題、類別標記或摘要,您必須先擷取含有相關網站的 SiteEntry
,修改一或多個屬性,然後呼叫 SiteEntry
的 update()
方法。以下範例會修改先前網站的主題,並重新命名網站:
myTwin.setTitle(new PlainTextConstruct("better-title")); Theme theme = myTwin.getTheme(); theme.setValue('iceberg'); myTwin.setTheme(theme); myTwin.getCategories().add(new Category(TagCategory.Scheme.TAG, "newTag", null)); SiteEntry updatedSiteEntry = myTwin.update(); System.out.println(updatedSiteEntry.getTitle().getPlainText();
網址對應
網址對應可讓協作平台使用者將自己的網域對應至 Google 協作平台。舉例來說,您可以使用 http://www.mydomainsite.com
取代 http://sites.google.com/a/domain.com/mysite
。視網站的託管位置而定,您可以手動修改網站的網址對應項目。詳情請參閱說明中心文章。
擷取網站的網址對應
如要傳回網站的網址對應項目,請使用 with-mappings=true
參數擷取網站項目/動態饋給:
SiteQuery query = new SiteQuery(new URL("https://sites.google.com/feeds/site/siteName")); query.setWithMappings(true); SiteFeed feed = service.getFeed(query, SiteFeed.class); for (SiteEntry entry : feed.getEntries()) { System.out.println("Mappings for '" + entry.getSiteName().getValue() + "':"); for (Link link : entry.getWebAddressMappingLinks()) { System.out.println(" " + link.getHref()); } }
現有的對應會顯示為包含 rel='webAddressMapping' 的 link
。舉例來說,在上述範例中,有三個 webAddressMapping
指向網站 http://sites.google.com/site/myOtherTestSite
。
修改網址對應
注意:使用網址對應功能時,所有 GET/POST/PUT 作業都應指定 with-mappings=true
參數。如果沒有這個參數,系統就不會在網站項目中傳回 webAddressMapping
(GET),也不會在更新/移除 (PUT) 項目對應項目時考量。
如要新增、更新或刪除對應,只要在建立新網站或更新網站中繼資料時,指定、變更或移除這類連結即可。網站動態饋給 URI 中必須包含 with-mappings=true
參數。注意:如要更新位址對應項目,您必須是網站管理員,或是 G Suite 代管網站的網域管理員。
舉例來說,下方的要求會更新 http://www.mysitemapping.com
對應至 http://www.my-new-sitemapping.com
的對應關係,並移除 http://www.mysitemapping2.com
,將資料移出項目:
SiteEntry entry = client.getEntry(new URL("https://sites.google.com/feeds/site/site/siteName?with-mappings=true"), SiteEntry.class); // Modify mappings (remove all mappings, add some of them again, add modified mappings) entry.removeLinks(SitesLink.Rel.WEBADDRESSMAPPING, Link.Type.HTML); entry.addLink(SitesLink.Rel.WEBADDRESSMAPPING, Link.Type.HTML, "http://www.my-new-sitemapping.com"); // Update the entry with the mappings. entry.update();
請注意,您也可以在建立/複製協作平台時指定網址對應。
活動動態消息
您可以擷取活動動態饋給,擷取網站的近期活動 (變更)。活動動態饋給中的每個項目都包含關於「網站」變更的資訊。
如要查詢活動動態消息,請將 HTTP GET
傳送至活動動態消息網址:
https://sites.google.com/feeds/activity/site/siteName
在 Java 用戶端中,使用 ActivityFeed
類別傳回 ActivityEntry
物件:
public String buildActivityFeedUrl() { String domain = "site"; // OR if the Site is hosted on G Suite, your domain (e.g. example.com) String siteName = "mySite"; return "https://sites.google.com/feeds/activity/" + domain + "/" + siteName + "/"; } public void getActivityFeed() throws IOException, ServiceException { ActivityFeed activityFeed = client.getFeed(new URL(buildActivityFeedUrl()), ActivityFeed.class); for (BaseActivityEntry<?> entry : activityFeed.getEntries()){ System.out.println(entry.getSummary().getPlainText()); System.out.println(" revisions link: " + entry.getRevisionLink().getHref()); } }
注意:您必須是網站的協作者或擁有者,才能存取動態饋給。 您的用戶端必須使用 AuthSub、OAuth 或 ClientLogin 權杖進行驗證。請參閱「驗證協作平台服務」。
修訂動態饋給
如要擷取任何內容項目的修訂版本記錄,請將 HTTP GET
傳送至項目的修訂版本連結:
https://sites.google.com/feeds/revision/site/siteName/CONTENT_ENTRY_ID
這個範例會查詢內容動態饋給,然後擷取第一個內容項目的修訂動態饋給:
ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl()), ContentFeed.class); URL revisionFeedUrl = new URL(contentFeed.getEntries().get(0).getRevisionLink().getHref()); // use first entry public void getRevisionFeed(String revisionFeedUrl) throws IOException, ServiceException { RevisionFeed revisionFeed = client.getFeed(revisionFeedUrl, RevisionFeed.class); for (BaseContentEntry<?> entry : revisionFeed.getEntries()){ System.out.println(entry.getTitle().getPlainText()); System.out.println(" updated: " + entry.getUpdated().toUiString() + " by " + entry.getAuthors().get(0).getEmail()); System.out.println(" revision #: " + entry.getRevision().getValue()); } }
注意:您必須是協作平台的協作者或擁有者,才能存取這份動態饋給。 您的用戶端必須使用 AuthSub、OAuth 或 ClientLogin 權杖進行驗證。請參閱「驗證協作平台服務」。
內容動態饋給
擷取內容動態饋給
內容動態饋給會列出網站的最新內容。只要將 HTTP GET
傳送至內容動態饋給網址,即可存取:
https://sites.google.com/feeds/content/site/siteName
動態饋給參數 | 說明 |
---|---|
site | 「site 」或 G Suite 代管網域的網域 (例如 example.com )。 |
siteName | 網站的網域名稱,位於網站網址中 (例如 mySite )。 |
擷取內容動態饋給的範例:
public String buildContentFeedUrl() { String domain = "site"; // OR if the Site is hosted on G Suite, your domain (e.g. example.com) String siteName = "mySite"; return "https://sites.google.com/feeds/content/" + domain + "/" + siteName + "/"; } ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl()), ContentFeed.class);
產生的 contentFeed
是 ContentFeed
物件,內含伺服器的回應。contentFeed
的每個項目都代表使用者網站中的不同網頁或項目。ContentFeed
會包含不同類型的物件,皆繼承自 BaseContentEntry
:ListItemEntry
、ListPageEntry
、AttachmentEntry
、WebAttachmentEntry
、FileCabinetPageEntry
、AnnouncementsPageEntry
、AnnouncementEntry
、WebPageEntry
、CommentEntry
。
以下範例說明如何在 ContentFeed
中列出不同類型的項目。每個項目類型都包含不同的屬性,但並非所有屬性都會列印在這裡。
public String getContentBlob(BaseContentEntry<?> entry) { return ((XhtmlTextConstruct) entry.getTextContent().getContent()).getXhtml().getBlob(); } // Extracts an entry's numeric ID. private String getEntryId(String selfLink) { return selfLink.substring(selfLink.lastIndexOf("/") + 1); } public void printContentEntries(ContentFeed contentFeed) { System.out.println("Listing all WebPageEntry:"); for (WebPageEntry entry : contentFeed.getEntries(WebPageEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); System.out.println(" id: " + getEntryId(entry)); if (entry.getParentLink() != null) { System.out.println(" parent id: " + getEntryId(entry.getParentLink().getHref())); } System.out.println(" author: " + entry.getAuthors().get(0).getEmail()); System.out.println(" content: " + getContentBlob(entry)); } System.out.println("Listing all ListPageEntry:"); for (ListPageEntry entry : contentFeed.getEntries(ListPageEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); System.out.println(" id: " + getEntryId(entry)); for (Column col : entry.getData().getColumns()) { System.out.print(" [" + col.getIndex() + "] " + col.getName() + "\t"); } } for (ListItemEntry entry : contentFeed.getEntries(ListItemEntry.class)) { for (Field field : entry.getFields()) { System.out.print(" [" + field.getIndex() + "] " + field.getValue() + "\t"); } System.out.println("\n"); } System.out.println("Listing all FileCabinetPageEntry:"); for (FileCabinetPageEntry entry : contentFeed.getEntries(FileCabinetPageEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); System.out.println(" id: " + getEntryId(entry)); System.out.println(" content: " + getContentBlob(entry)); } System.out.println("Listing all CommentEntry:"); for (CommentEntry entry : contentFeed.getEntries(CommentEntry.class)) { System.out.println(" in-reply-to: " + entry.getInReplyTo().toString()); System.out.println(" content: " + getContentBlob(entry)); } System.out.println("Listing all AnnouncementsPageEntry:"); for (AnnouncementsPageEntry entry : contentFeed.getEntries(AnnouncementsPageEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); System.out.println(" id: " + getEntryId(entry)); System.out.println(" content: " + getContentBlob(entry)); } System.out.println("Listing all AnnouncementEntry:"); for (AnnouncementEntry entry : contentFeed.getEntries(AnnouncementEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); System.out.println(" id: " + getEntryId(entry)); if (entry.getParentLink() != null) { System.out.println(" parent id: " + getEntryId(entry.getParentLink().getHref())); } System.out.println(" draft?: " + entry.isDraft()); System.out.println(" content: " + getContentBlob(entry)); } System.out.println("Listing all AttachmentEntry:"); for (AttachmentEntry entry : contentFeed.getEntries(AttachmentEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); System.out.println(" id: " + getEntryId(entry)); if (entry.getParentLink() != null) { System.out.println(" parent id: " + getEntryId(entry.getParentLink().getHref())); } if (entry.getSummary() != null) { System.out.println(" description: " + entry.getSummary().getPlainText()); } System.out.println(" revision: " + entry.getRevision().getValue()); MediaContent content = (MediaContent) entry.getContent(); System.out.println(" src: " + content.getUri()); System.out.println(" content type: " + content.getMimeType().getMediaType()); } System.out.println("Listing all WebAttachmentEntry:"); for (WebAttachmentEntry entry : contentFeed.getEntries(WebAttachmentEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); System.out.println(" id: " + getEntryId(entry)); if (entry.getParentLink() != null) { System.out.println(" parent id: " + getEntryId(entry.getParentLink().getHref())); } if (entry.getSummary() != null) { System.out.println(" description: " + entry.getSummary().getPlainText()); } System.out.println(" src: " + ((MediaContent) entry.getContent()).getUri()); } }
注意:這項動態饋給可能需要驗證,也可能不需要驗證,具體取決於網站的分享權限。如果網站不是公開網站,您的用戶端必須使用 AuthSub、OAuth 或 ClientLogin 權杖進行驗證。請參閱「驗證協作平台服務」。
內容動態饋給查詢範例
您可以使用部分 標準 Google Data API 查詢參數和傳統 Sites API 專屬參數,搜尋內容動態饋給。如需進一步瞭解相關資訊,以及取得支援參數的完整清單,請參閱參考指南。
注意:本節中的範例使用「擷取內容動態饋給」中的 buildContentFeedUrl()
方法。
擷取特定項目種類
如果只要擷取特定類型的項目,請使用 kind
參數。這個範例只會傳回 attachment
項目:
ContentQuery query = new ContentQuery(new URL(buildContentFeedUrl())); query.setKind("webpage"); ContentFeed contentFeed = client.getFeed(query, ContentFeed.class); for (AttachmentEntry entry : contentFeed.getEntries(AttachmentEntry.class)) { System.out.println(entry.getTitle().getPlainText()); }
如要傳回多個項目類型,請使用「,」分隔每個 kind
。這個範例會傳回 filecabinet
和 listpage
項目:
URL url = new URL(buildContentFeedUrl() + "?kind=filecabinet,listpage"); ContentFeed contentFeed = client.getFeed(url, ContentFeed.class); for (FileCabinetPageEntry entry : contentFeed.getEntries(FileCabinetPageEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); } for (ListPageEntry entry : contentFeed.getEntries(ListPageEntry.class)) { System.out.println(" title: " + entry.getTitle().getPlainText()); }
按路徑擷取網頁
如果您知道 Google 網站中網頁的相對路徑,可以使用 path
參數擷取該特定網頁。這個範例會傳回位於 http://sites.google.com/site/siteName/path/to/the/page
的頁面:
ContentQuery query = new ContentQuery(new URL(buildContentFeedUrl())); query.setPath("/path/to/the/page"); ContentFeed contentFeed = client.getFeed(query, ContentFeed.class); for (BaseContentEntry<?> entry : contentFeed.getEntries()) { System.out.println(" title: " + entry.getTitle().getPlainText()); }
擷取父頁面下的所有項目
如果您知道網頁的內容項目 ID (例如以下範例中的「1234567890」),即可使用 parent
參數擷取其所有子項目 (如有):
ContentQuery query = new ContentQuery(new URL(buildContentFeedUrl())); query.setParent("1234567890"); ContentFeed contentFeed = client.getFeed(query, ContentFeed.class);
如需其他參數,請參閱參考指南。
建立內容
注意:在建立網站內容之前,請務必先在用戶端設定網站。client.site = "siteName";
您可以將 HTTP POST
傳送至內容動態饋給,藉此建立新內容 (網頁、清單頁面、檔案櫃頁面、公告頁面等):
https://sites.google.com/feeds/content/site/siteName
如需支援節點類型的清單,請參閱參考指南中的 kind
參數。
建立新項目 / 頁面
本例會在網站頂層下建立新的 webpage
,加入一些用於頁面內文的 XHTML,並將標題標題設為「New WebPage Title」:
private void setContentBlob(BaseContentEntry<?> entry, String pageContent) { XmlBlob xml = new XmlBlob(); xml.setBlob(pageContent); entry.setContent(new XhtmlTextConstruct(xml)); } public WebPageEntry createWebPage(String title, String content) throws MalformedURLException, IOException, ServiceException { WebPageEntry entry = new WebPageEntry(); entry.setTitle(new PlainTextConstruct(title)); setContentBlob(entry, content); // Entry's HTML content return client.insert(new URL(buildContentFeedUrl()), entry); } WebPageEntry createdEntry = createWebPage("New Webpage Title", "<b>HTML content</b>"); System.out.println("Created! View at " + createdEntry.getHtmlLink().getHref());
如果要求成功,createdEntry
就會包含在伺服器上建立的項目副本。
在自訂網址路徑下建立項目/網頁
根據預設,上例會在網址 http://sites.google.com/site/siteName/new-webpage-title
下方建立,並設有「New Webpage Title」網頁標題。也就是說,<atom:title>
會經過正規化處理,成為網址的 new-webpage-title
。如要自訂網頁網址的網址路徑,請設定 <sites:pageName>
元素。
這個範例會建立新的 filecabinet
頁面,標題為「File Storage」,但會透過指定 <sites:pageName>
元素,在網址 http://sites.google.com/site/siteName/files
(而非 http://sites.google.com/site/siteName/file-storage
) 下方建立該頁面。
public FileCabinetPageEntry createFileCabinetPage(String title, String content, String customPageName) throws MalformedURLException, IOException, ServiceException { FileCabinetPageEntry entry = new FileCabinetPageEntry(); entry.setTitle(new PlainTextConstruct(title)); setContentBlob(entry, content); // Entry's HTML content entry.setPageName(new PageName(customPageName)); // Upload to a custom page path return client.insert(new URL(buildContentFeedUrl()), entry); } FileCabinetPageEntry createdEntry = createFileCabinetPage("File Storage", "<b>HTML content</b>", "files"); System.out.println("Created! View at " + createdEntry.getHtmlLink().getHref());
伺服器會使用下列優先順序規則命名網頁的網址路徑:
<sites:pageName>
(如果有的話)。必須符合「a-z, A-Z, 0-9, -, _
」的規定。<atom:title>
,如果沒有 pageName,則不得為空值。標準化是指將空白字元裁減 + 縮減為「-」並移除不符合a-z, A-Z, 0-9, -, _
的字元。
建立子頁面
如要在父項頁面下建立子頁面 (下層),您必須在項目中設定上層連結。連結的 href
屬性連結至父項節點的自我連結。
public AnnouncementEntry postAnnouncement(String title, String content, AnnouncementsPageEntry parentPage) throws MalformedURLException, IOException, ServiceException { AnnouncementEntry entry = new AnnouncementEntry(); entry.setTitle(new PlainTextConstruct(title)); setContentBlob(entry, content); // Entry's HTML content // Set the entry's parent link to create the announcement under that page. entry.addLink(SitesLink.Rel.PARENT, Link.Type.ATOM, parentPage.getSelfLink().getHref()); return client.insert(new URL(buildContentFeedUrl()), entry); } ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl() + "?kind=announcementspage"), ContentFeed.class); AnnouncementEntry createdEntry = postAnnouncement("Party!!", "My place, this weekend", contentFeed.getEntries().get(0)); System.out.println("New post by " + createdEntry.getAuthors().get(0).getName());
上方的範例會在使用者內容動態中找到的第一個公告頁面下方建立新的 announcement
。公告標題設為「Party!!」,內容設為「本週末,我家見」。
頁面範本
建立頁面範本
建立網頁範本的程序與建立新項目/網頁和建立子網頁的程序相同。差別在於,您需要新增 category
,並將詞彙和標籤分別設為「http://schemas.google.com/g/2005#template」和「template」。
這個範例會建立新的 webpage
範本。
// The template webpage entry. WebPageEntry entry = new WebPageEntry(); // Set title and content. entry.setTitle(new PlainTextConstruct("Page template title")); XmlBlob xml = new XmlBlob(); xml.setBlob("Content for page template"); entry.setContent(new XhtmlTextConstruct(xml)); // Set the template category Category TEMPLATE_CATEGORY = new Category(TemplateCategory.Scheme.LABELS, TemplateCategory.Term.TEMPLATE, TemplateCategory.Label.TEMPLATE); entry.getCategories().add(TEMPLATE_CATEGORY); // Insert the template webpage entry. WebPageEntry createdEntry = client.insert(new URL("https://sites.google.com/feeds/content/site/siteName"), entry);
使用範本建立頁面
與建立頁面範本類似,您可以加入 <link>
且指向頁面範本自我連結的 <link>
,從範本例項化新頁面。
本範例會建立新的 filecabinet
範本,然後利用該範本將新的 filecabinet
頁面執行個體化。
URL feedUrl = new URL("https://sites.google.com/feeds/content/site/siteName"); // 1. Create file cabinet page template FileCabinetPageEntry inputTemplateEntry = new FileCabinetPageEntry(); inputTemplateEntry.setTitle(new PlainTextConstruct("File cabinet page template title")); XmlBlob xml = new XmlBlob(); xml.setBlob("Content for page template"); inputTemplateEntry.setContent(new XhtmlTextConstruct(xml)); // Set the template category Category TEMPLATE_CATEGORY = new Category(TemplateCategory.Scheme.LABELS, TemplateCategory.Term.TEMPLATE, TemplateCategory.Label.TEMPLATE); inputTemplateEntry.getCategories().add(TEMPLATE_CATEGORY); // 2. Create file cabinet page template instance FileCabinetPageEntry templateEntry = client.insert(feedUrl, inputTemplateEntry); // Specify link to the page template FileCabinetPageEntry templateInstanceEntry = new FileCabinetPageEntry(); templateInstanceEntry.setTitle(new PlainTextConstruct("File cabinet template instance")); templateInstanceEntry.addLink(new Link(SitesLink.Rel.TEMPLATE, Link.Type.ATOM, templateEntry.getSelfLink().getHref())); FileCabinetPageEntry createdFileCabinetFromTemplate = client.insert(feedUrl, templateInstanceEntry);
注意:雖然範本會定義 <category>
,但仍需納入項目。另請注意,如果您加入 <content>
元素,伺服器會拒絕該元素。
正在上傳檔案
和 Google 協作平台一樣,這個 API 支援將附件上傳到檔案櫃頁面或上層頁面。
如要將附件上傳至父項,請向內容動態饋給網址傳送 HTTP POST
要求:
https://sites.google.com/feeds/content/site/siteName
所有附件類型都必須上傳至上層頁面。因此,您需要在嘗試上傳的 AttachmentEntry
或 WebAttachmentEntry
物件上設定父項連結。詳情請參閱「建立子頁面」。
正在上傳附件
在此範例中,系統會將 PDF 檔案上傳到使用者內容動態饋給中的第一個 FileCabinetPageEntry
。附件會以「Getting Started」為標題建立,並提供「HR packet」(人力資源封包) 的說明 (選用)。
MimetypesFileTypeMap mediaTypes = new MimetypesFileTypeMap(); mediaTypes.addMimeTypes("application/msword doc"); mediaTypes.addMimeTypes("application/vnd.ms-excel xls"); mediaTypes.addMimeTypes("application/pdf pdf"); mediaTypes.addMimeTypes("text/richtext rtx"); // ... See a more complete list of mime types in the SitesHelper.java public AttachmentEntry uploadAttachment(File file, BasePageEntry<?> parentPage, String title, String description) throws IOException, ServiceException { AttachmentEntry newAttachment = new AttachmentEntry(); newAttachment.setMediaSource(new MediaFileSource(file, mediaTypes.getContentType(file))); newAttachment.setTitle(new PlainTextConstruct(title)); newAttachment.setSummary(new PlainTextConstruct(description)); newAttachment.addLink(SitesLink.Rel.PARENT, Link.Type.ATOM, parentPage.getSelfLink().getHref()); return client.insert(new URL(buildContentFeedUrl()), newAttachment); } ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl() + "?kind=filecabinet"), ContentFeed.class); FileCabinetPageEntry parentPage = contentFeed.getEntries(FileCabinetPageEntry.class).get(0); AttachmentEntry attachment = uploadAttachment( new File("/path/to/your/file.pdf"), parentPage, "Getting Started", "HR packet"); System.out.println("Uploaded!");
如果上傳成功,attachment
就會包含已建立的附件項目副本。
將附件上傳至資料夾
如要將附件上傳至 FileCabinetPageEntry
中現有的資料夾,請加入類別,並將「term」屬性設為資料夾名稱。例如,在 uploadAttachment()
中加入這一行:
newAttachment.getCategories().add(new Category("http://schemas.google.com/sites/2008#folder", "FolderName"));
網頁附件
網頁附件是一種特殊類型的附件。基本上,這些連結是網頁上其他檔案的連結,可新增至檔案櫃清單。這項功能類似於 Google 協作平台使用者介面中的「透過網址新增檔案」上傳方法。
注意:只能在檔案櫃下方建立網頁附件。但無法上傳至其他類型的網頁。
這個範例會在使用者內容動態消息中找到的第一個 FileCabinetPageEntry
下方建立 WebAttachmentEntry
。其標題和 (選用) 說明分別設為「GoogleLogo」和「nice color」。
public WebAttachmentEntry uploadWebAttachment(String contentUrl, FileCabinetPageEntry filecabinet, String title, String description) throws MalformedURLException, IOException, ServiceException { MediaContent content = new MediaContent(); content.setUri(contentUrl); WebAttachmentEntry webAttachment = new WebAttachmentEntry(); webAttachment.setTitle(new PlainTextConstruct(title)); webAttachment.setSummary(new PlainTextConstruct(description)); webAttachment.setContent(content); webAttachment.addLink(SitesLink.Rel.PARENT, Link.Type.ATOM, filecabinet.getSelfLink().getHref()); return client.insert(new URL(buildContentFeedUrl()), webAttachment); } ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl() + "?kind=filecabinet"), ContentFeed.class); FileCabinetPageEntry parentPage = contentFeed.getEntries(FileCabinetPageEntry.class).get(0); WebAttachmentEntry webAttachment = uploadWebAttachment("http://www.google.com/images/logo.gif", parentPage, "Google's Logo", "nice colors"); System.out.println("Web attachment created!");
POST
會在使用者的檔案櫃中建立連結,指向位於「http://www.google.com/images/logo.gif」的圖片。
更新內容
更新網頁的中繼資料和/或 HTML 內容
您可以使用項目的 update()
方法編輯任一 BaseContentEntry
類型的中繼資料 (標題、pageName 等) 和網頁內容。這會將 HTTP PUT
要求傳送至項目的 edit
連結。
以下是透過以下變更更新 ListPageEntry
的範例:
- 標題已改為「已更新標題」
- 網頁的 HTML 內容已更新為「<p>Updated HTML Content</p>」
- 清單的第一個欄標題已變更為「Owner」
ContentFeed contentFeed = client.getFeed( new URL(buildContentFeedUrl() + "?kind=listpage"), ContentFeed.class); ListPageEntry listPage = contentFeed.getEntries(ListPageEntry.class).get(0); // Update first list page found // Update title listPage.setTitle(new PlainTextConstruct("Updated Title")); // Update HTML content XmlBlob xml = new XmlBlob(); xml.setBlob("<p>Updated HTML Content</p>"); listPage.setContent(new XhtmlTextConstruct(xml)); // Change first column's heading listPage.getData().getColumns().get(0).setName("Owner"); // listPage.setPageName(new PageName("new-page-path")); // You can also change the page's URL path ListPageEntry updatedEntry = listPage.update(); System.out.println("ListPage updated!");
更新附件檔案內容
如果是 AttachmentEntry
,您也可以設定項目的 MediaSource
,然後使用該項目的 updateMedia(boolean)
方法來更新內容。
以下範例會更新現有附件的內容:
public AttachmentEntry updateFile(AttachmentEntry entry, File newFile) throws IOException, ServiceException { // See Uploading Attachments for the definition of mediaTypes. entry.setMediaSource(new MediaFileSource(newFile, mediaTypes.getContentType(newFile))); return entry.updateMedia(false); }
這個範例會將 HTTP PUT
要求傳送至項目的 edit-media
連結。傳回的 AttachmentEntry
會包含更新後的內容。
更新附件中繼資料和內容
您可以使用 updateMedia()
方法,在同一個呼叫中更新附件的中繼資料和內容。是否可以只更新檔案內容或中繼資料,或同時更新兩者。
這個範例會將附件的標題變更為「New Title」,更新說明,並將檔案內容替換為新的 .zip 檔案。由於要求包含新的檔案內容,因此會使用 AttachmentEntry
的 updateMedia()
。
public AttachmentEntry updateAttachment(AttachmentEntry entry, File newFile, String newTitle, String newDescription) throws IOException, ServiceException { // See Uploading Attachments for the definition of mediaTypes. entry.setMediaSource(new MediaFileSource(newFile, mediaTypes.getContentType(newFile))); entry.setTitle(new PlainTextConstruct(newTitle)); entry.setSummary(new PlainTextConstruct(newDescription)); return entry.updateMedia(true); } ContentFeed contentFeed = client.getFeed( new URL(buildContentFeedUrl() + "?kind=attachment&max-results=1"), ContentFeed.class); AttachmentEntry attachment = contentFeed.getEntries(AttachmentEntry.class).get(0); // Update first attachment found AttachmentEntry updatedAttachment = updateAttachment(attachment, new File("/path/to/file.zip"), "New Title", "better stuff");
刪除內容
如要從 Google 網站移除網頁或項目,請先擷取內容項目,然後呼叫項目的 delete()
。
entry.delete();
您也可以使用服務類別的 delete()
方法,將項目的 edit
連結和 ETag 值傳遞給該方法:
client.delete(entry.getEditLink().getHref(), "*"); // Note: using "*" may overwrite another client's changes.
如果項目已成功刪除,伺服器會傳回 HTTP 200 OK
。
下載附件
如要下載 AttachmentEntry
,請將 HTTP GET
要求傳送至項目的內容 src 連結。
以下範例會將使用者內容動態消息中找到的第一個 AttachmentEntry
下載至「/path/to/save/file/」目錄:
private void downloadFile(String downloadUrl, String fullFilePath) throws IOException, ServiceException { System.out.println("Downloading file from: " + downloadUrl); MediaContent mc = new MediaContent(); mc.setUri(downloadUrl); MediaSource ms = service.getMedia(mc); InputStream inStream = null; FileOutputStream outStream = null; try { inStream = ms.getInputStream(); outStream = new FileOutputStream(fullFilePath); int c; while ((c = inStream.read()) != -1) { outStream.write(c); } } finally { if (inStream != null) { inStream.close(); } if (outStream != null) { outStream.flush(); outStream.close(); } } } public void downloadAttachment(AttachmentEntry entry, String directory) throws IOException, ServiceException { String url = ((OutOfLineContent) entry.getContent()).getUri(); downloadFile(url, directory + entry.getTitle().getPlainText()); // Use entry's title for the save filename } ContentFeed contentFeed = client.getFeed( new URL(buildContentFeedUrl() + "?kind=attachment&max-results=1"), ContentFeed.class); downloadAttachment(contentFeed.getEntries(AttachmentEntry.class).get(0), "/path/to/save/file/"); System.out.println("Downloaded.");
ACL 動態饋給
共用權限 (ACL) 總覽
ACL 動態饋給中的每個 ACL 項目都代表特定實體的存取權角色,該實體可以是使用者、一組使用者、網域或預設存取權 (即公開網站)。系統只會顯示明確存取權實體的項目,在 Google Sites UI 的「存取權使用者」面板中,每個電子郵件地址都會顯示一筆項目。因此,即使網域管理員有隱含的網站存取權,也不會顯示。
角色
角色元素代表實體可擁有的存取層級。gAcl:role
元素有四個可能的值:
- Reader — 檢視者 (相當於唯讀權限)。
- writer:協作者 (等同於讀取/寫入權限)。
- owner:通常為網站管理員 (相當於讀取/寫入權限)。
範圍
範圍元素代表具有此存取層級的實體。gAcl:scope
元素分為四種類型:
- user - 電子郵件地址值,例如「user@gmail.com」。
- group:Google 網路論壇電子郵件地址,例如「group@domain.com」。
- domain:G Suite 網域名稱,例如「domain.com」。
- 預設:只有一個可能的「預設」類型範圍,且沒有任何值 (例如
<gAcl:scope type="default">
)。這個特定範圍會控制任何使用者在公開網站上預設的存取權。
注意:網域的 gAcl:role
值不得設為「owner」存取權,只能是讀取或寫入權限。
擷取 ACL 資訊提供
AclFeed
和 AclEntry
類別可用於控制網站的分享權限,並可透過服務類別的 getFeed()
方法擷取。
以下範例會擷取特定網站的 ACL 動態饋給,並列印每個 AclEntry
的權限:
public String getAclFeedUrl(String siteName) { String domain = "site"; // OR if the Site is hosted on G Suite, your domain (e.g. example.com) return "https://sites.google.com/feeds/acl/site/" + domain + "/" + siteName + "/"; } public void getAclFeed(String siteName) throws IOException, ServiceException { AclFeed aclFeed = client.getFeed(new URL(getAclFeedUrl(siteName)), AclFeed.class); for (AclEntry entry : aclFeed.getEntries()) { System.out.println(entry.getScope().getValue() + " (" + entry.getScope().getType() + ") : " + entry.getRole().getValue()); } } getAclFeed('my-site-name');
如果您使用 SiteFeed 中的項目,每個 SiteEntry
都會包含一個指向其 ACL 資訊提供的連結。例如,以下程式碼片段會擷取 SiteEntry
的 ACL 動態饋給:
String aclLink = siteEntry.getLink(SitesAclFeedLink.Rel.ACCESS_CONTROL_LIST, Link.Type.ATOM).getHref(); AclFeed aclFeed = client.getFeed(new URL(aclLink), AclFeed.class);
共用網站
注意:只有在網域設定允許這類權限時,才能使用特定的共用 ACL (例如,如果啟用 G Suite 網域的網域外共用功能)。
如要使用 API 共用 Google 網站,您的用戶端必須建立新的 AclEntry
並將其 POST
至伺服器。
以下範例將「user@example.com」新增為網站的 reader
:
AclRole role = new AclRole("reader"); AclScope scope = new AclScope(AclScope.Type.USER, "user@example.com"); AclEntry aclEntry = addAclRole(role, scope, entry); public AclEntry addAclRole(AclRole role, AclScope scope, SiteEntry siteEntry) throws IOException, MalformedURLException, ServiceException { AclEntry aclEntry = new AclEntry(); aclEntry.setRole(role); aclEntry.setScope(scope); Link aclLink = siteEntry.getLink(SitesAclFeedLink.Rel.ACCESS_CONTROL_LIST, Link.Type.ATOM); return client.insert(new URL(aclLink.getHref()), aclEntry); }
如要瞭解可能的 AclScope
和 AclRoles
值,請參閱「ACL 動態饋給總覽」一節。
群組和網域層級共用
與與單一使用者共用網站類似,您也可以透過 Google 群組或 G Suite 網域共用網站。
共用群組電子郵件地址:
AclScope scope = new AclScope(AclScope.Type.GROUP, "group_name@example.com");
與整個網域共用:
AclScope scope = new AclScope(AclScope.Type.DOMAIN, "example.com");
只有 G Suite 網域支援在網域層級共用檔案,而且只適用於代管該網站的網域。 舉例來說,http://sites.google.com/a/domain1.com/siteA 只能與 domain1.com 共用整個網站,而非 domain2.com。如果網站並非託管在 G Suite 網域上 (例如 http://sites.google.com/site/siteB),就無法邀請網域。
修改共用權限
如要在網站上現有的共用權限,請先擷取相關的 AclEntry
,視需要修改權限,然後呼叫 AclEntry
的 update()
方法來修改伺服器上的 ACL。
這個範例會修改「共用網站」一節中的先前 aclEntry
範例,將「user@example.com」更新為 writer
(協作者):
aclEntry.setRole(new AclRole("writer")); AclEntry updatedAclEntry = aclEntry.update(); // Could also use the client's update method // client.update(new URL(aclEntry.getEditLink().getHref()), aclEntry);
如要進一步瞭解 ETag,請參閱 Google Data API 參考指南。
正在移除共用權限
如要移除共用權限,請先擷取 AclEntry
,然後呼叫其 delete()
方法:
aclEntry.delete(); // Could also use the client's delete method // client.delete(new URL(aclEntry.getEditLink().getHref()), aclEntry);
如要進一步瞭解 ETag,請參閱 Google Data API 參考指南。
特殊主題
再次擷取動態饋給或項目
如果您想擷取先前擷取過的動態饋給或項目,可以提高效率,只要告訴伺服器只在該清單或項目自上次擷取後有所變動時傳送即可。
為執行這類的條件式擷取作業,getFeed()
和 getEntry()
方法都會提供額外引數,可接受 ETag 值或 If-Modified-Since
標頭的 DateTime
物件。您可以透過 entry.getEtag()
存取項目的 etag。
以下範例會針對內容網頁項目執行條件式擷取:
String feedUrl = "https://sites.google.com/feeds/content/site/siteName/123456789"; WebPageEntry entry = client.getEntry(new URL(feedUrl), WebPageEntry.class, "\"GVQHSARDQyp7ImBq\"");
當伺服器收到這項要求時,會檢查您要求的項目是否與您指定的 ETag 相同。如果 ETag 相符,表示項目未變更,且伺服器會傳回 HTTP 304 NotModifiedException
例外狀況。
如果 ETag 不相符,表示自您上次要求該項目以來,該項目已遭修改,且伺服器會傳回該項目。
如要進一步瞭解 ETag,請參閱 Google Data API 參考指南。