重要事項:這份文件是在 2012 年前撰寫,本文所述的驗證選項 (OAuth 1.0、AuthSub 和 ClientLogin) 已於 2012 年 4 月 20 日正式淘汰,目前無法使用。建議您盡快改用 OAuth 2.0。
Google Sites Data API 可讓用戶端應用程式存取、發布及修改 Google 網站中的內容。 用戶端應用程式也可以要求取得近期活動清單、擷取修訂版本記錄,以及下載附件。
除了簡要介紹 Google 協作平台資料 API 的功能,本指南也提供使用 Java 用戶端程式庫與 API 互動的範例。如需設定用戶端程式庫的說明,請參閱「開始使用 Google Data Java 用戶端程式庫」。如要進一步瞭解 Java 用戶端程式庫與傳統版 Google 協作平台 API 互動時使用的基礎通訊協定,請參閱通訊協定指南。
觀眾
本文適用於想編寫用戶端應用程式,並使用 Google Data Java 用戶端程式庫與 Google 協作平台互動的開發人員。
開始使用
Google 協作平台會使用 Google 帳戶或 G Suite 帳戶進行驗證,如果已有帳戶,就沒問題了。 否則,請建立新帳戶。
安裝程式庫
如需設定及安裝用戶端程式庫的相關說明,請參閱「開始使用 Google Data Java 用戶端程式庫」。如果您使用 Eclipse,該文章也會說明如何使用 Google Data APIs Eclipse 外掛程式設定專案。開始使用前,請先確認以下事項:
安裝 .jar 後,您需要在專案中加入下列項目:
java/lib/gdata-sites-2.0.jar- 這裡的 2.0 版適用於傳統 Sites API 1.4 版。java/lib/gdata-core-1.0.jarjava/lib/gdata-client-1.0.jarjava/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 執行多項作業,瞭解如何使用傳統版協作平台 API。
請注意,您必須加入 java/sample/util/lib/sample-util.jar 才能執行範例。
開始自己的專案
提示:如要使用 Eclipse 外掛程式快速設定,請參閱「使用 Eclipse 搭配 Google Data API」一文。
視應用程式需求而定,您需要匯入多個項目。建議您從下列匯入項目開始:
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。
通過傳統版 Google 協作平台 API 驗證
您可以使用 Java 用戶端程式庫處理公開或私人動態消息。視 Google 協作平台權限和您嘗試執行的作業而定,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 協作平台使用者的使用者名稱和密碼,只需要 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 處理常式使用的查詢參數):
- 下一個網址:使用者登入帳戶並授予存取權後,Google 會將使用者重新導向這個網址;
http://www.example.com/welcome.jsp在上述範例中 - 範圍 - 上述範例中的
https://sites.google.com/feeds/ - 布林值,指出權杖是否會用於已註冊模式;
false在上述範例中 - 第二個布林值,用於指出符記稍後是否會換取工作階段符記;
true在上述範例中
升級為工作階段權杖
請參閱「使用 Google Data API 用戶端程式庫搭配 AuthSub」。
擷取工作階段權杖的相關資訊
請參閱「使用 Google Data API 用戶端程式庫搭配 AuthSub」。
撤銷工作階段權杖
適用於網頁或已安裝/行動應用程式的 OAuth
OAuth 可做為 AuthSub 的替代方案,適用於網路應用程式。OAuth 與 AuthSub 的安全且已註冊模式類似,所有資料要求都必須經過數位簽章,且您必須註冊網域。
查看如何將 OAuth 整合至已安裝的應用程式
擷取要求權杖
請參閱「使用 OAuth 搭配 Google Data API 用戶端程式庫」。
授權要求權杖
請參閱「使用 OAuth 搭配 Google Data API 用戶端程式庫」。
升級為存取權杖
已安裝/行動應用程式的 ClientLogin
已安裝或行動應用程式需要向 Google 帳戶驗證使用者身分時,應使用 ClientLogin。首次執行時,應用程式會提示使用者輸入使用者名稱/密碼。後續要求會參照驗證權杖。
查看將 ClientLogin 併入已安裝應用程式的操作說明
如要使用 ClientLogin,請叫用 SitesService 物件的 setUserCredentials() 方法,該物件是從 GoogleService 繼承而來。指定使用者電子郵件地址和密碼,您的用戶端會代表該使用者提出要求。例如:
SitesService client = new SitesService("yourCo-yourAppName-v1"); client.setUserCredentials("example@gmail.com", "pa$$word");
提示:應用程式首次成功驗證使用者後,請將授權權杖儲存在資料庫中,以供日後使用。您不需要在每次執行應用程式時提示使用者輸入密碼。詳情請參閱「回呼授權權杖」。
如要進一步瞭解如何在 Java 應用程式中使用 ClientLogin,請參閱「Using ClientLogin with the Google Data API Client Libraries」(搭配 Google Data API 用戶端程式庫使用 ClientLogin)。
網站動態消息
網站動態消息可用於列出使用者擁有或具有檢視權限的 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 協作平台設定頁面中勾選了「將這個協作平台發布為範本」設定,該協作平台就是範本。
- 只要您是來源網站的擁有者,即可從其他網域複製網站。
更新網站中繼資料
如要重新命名網站、變更主題、類別標記或摘要,請先擷取包含相關網站的 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 協作平台使用者將自己的網域對應至 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()); } }
現有對應會顯示為 link,並附上 rel='webAddressMapping'。舉例來說,在上述範例中,有三個指向網站 http://sites.google.com/site/myOtherTestSite 的 webAddressMapping。
修改網址對應
注意:使用網址對應時,所有 GET/POST/PUT 作業都應指定 with-mappings=true 參數。如果缺少這個參數,系統就不會在網站項目 (GET) 中傳回 webAddressMapping,也不會在更新/移除項目中的對應 (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 頁面,並將標題設為「檔案儲存空間」,但會指定 <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。公告標題設為「派對!!」,內容則為「本週末在我家」。
頁面範本
建立頁面範本
建立網頁範本的程序與建立新項目/網頁和建立子網頁相同。不同之處在於新增 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>,並將 rel='http://schemas.google.com/sites/2008#template' 指向頁面範本的自我連結。
這個範例會建立新的 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 協作平台 UI 中的「透過網址新增檔案」上傳方法。
注意:網頁附件只能在檔案櫃中建立。無法上傳至其他類型的頁面。
這個範例會在使用者內容動態消息中找到的第一個 FileCabinetPageEntry 下方建立 WebAttachmentEntry。
標題和 (選用) 說明分別設為「GoogleLogo」和「nice colors」。
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,並進行下列變更:
- 標題已修改為「Updated Title」
- 網頁的 HTML 內容會更新為「<p>Updated HTML Content</p>」
- 清單的第一個欄標題會變更為「擁有者」
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();
您也可以傳遞項目的 edit 連結和 ETag 值,使用服務類別的 delete() 方法:
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 項目都代表特定實體的存取角色,包括使用者、使用者群組、網域或預設存取權 (即公開網站)。系統只會顯示具有明確存取權的實體項目,Google 協作平台 UI 分享畫面中「有權存取的使用者」面板中的每個電子郵件地址,都會顯示一個項目。因此,即使網域管理員具有網站的隱含存取權,系統也不會顯示他們。
角色
角色元素代表實體可擁有的存取層級。gAcl:role 元素有四個可能的值:
- 讀取者:檢視者 (等同於唯讀存取權)。
- writer:協作者 (等同於讀取/寫入權限)。
- 擁有者:通常是網站管理員 (相當於讀取/寫入權限)。
範圍
範圍元素代表具有這個存取層級的實體。gAcl:scope 元素有四種可能類型:
- 使用者:電子郵件地址值,例如「user@gmail.com」。
- 群組:Google 網路論壇電子郵件地址,例如「group@domain.com」。
- domain:G Suite 網域名稱,例如「domain.com」。
- default:類型為「default」的範圍只有一個,且沒有值 (例如
<gAcl:scope type="default">)。這個特定範圍會控管任何使用者在公開網站上的預設存取權。
注意:網域的 gAcl:role 值無法設為「擁有者」存取權,只能是讀者或寫手。
擷取 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 參考指南。