[PHOTO CMS] 利用Dural來架設相簿網站與支援多重相片上傳

其實之前就有在使用4images來架設相簿,不過由於本人喜歡一次選取多個相片上傳,所以有使用Jupload的Java Applet,偏偏最近IE更新與Java更新後一直無法正常作用,看來得更換新的相簿管理網站。

期間也是有試用過其他的相簿網站:

  • ZenPhoto
    • 看起來不錯,但是由於AppServ版本有點舊,無法正常安裝。可能晚些時間再研究。
  • Gallery
    • 3.0 不支援AppServ,安裝2.X之後整體功能完整。但是由於上傳界面還是屬於醜醜的Java Applet可能先當成備案,再看看有沒有其他的網站軟體。
  • Dural:
    • 算是老牌的CMS軟體,而且跟我覺得多重像片上傳的API Plupload整合的很好,現在可能會開始研究這個。

接下來就記錄一下如何利用Dural來架設相簿網站,我的環境有點舊,有需要的人再看吧:

[iOS][Three20]Mac Blog App 使用心得與 Three20 初體驗

從上個禮拜MBA入手之後,就開始研究關於Mac OS上面的一些操作。

首先要先弄好的就是撰寫Blog的系統,以下是一些研究心得:

 

Mac上撰寫Blog系統使用心得:

  1. Ecto: 其實很好用,但是有著致命的空行問題,看來不會修。放棄!
  2. Qumana: 對於貼上程式碼支援不好,貼圖也不方便。
  3. Blogo: 連Launch都不行,應該跟我的版本有關,繼續找找。
  4. ScriptFile:不算是App因為是Chrome extension (Filefox也有),支援算差!
  5. MarsEdit: 用到現在最佳的,不可以編輯隱藏blog,但是貼程式碼相當順暢!

參考文章:

 

這些試用過後,應該會繼續使用MarsEdit當作目前的方案 如果真的遇到無法解決的問題,灌VirtualBox弄個Win7來寫Blog也是有可能的。

 

以下是整理Three20的初步體驗心得:

  • 下載Three20 程式碼 http://three20.info/roadmap/1.0.6.2

  • 在Xcode建立一個View base App

  • 使用終端機輸入以下指令去把Framework加入

    python three20/src/scripts/ttmodule.py -p Three20Test1/Three20Test1.xcodeproj Three20 –xcode-version=4

    • 注意相關的路徑
  • 打開專案會看到相關Framework 加好了,接下來你需要的是找一些範例來展示Three20的火力

參考以下網頁找範例:

[iOS]在iPHONE上使用MEDIA PLAYER播放的相關程式碼

在iOS要撥放影片其實有兩種播放器的source可以使用。 一個就是Media Player (MPMoviePlayerController),另一個是AVPlayer (AV Foundation)。

這裡會介紹一些簡單使用Media Player的相關程式碼。 主要有幾個部分,第一個部份就是設定撥放來源,在這裡是使用網路上的檔案。

接下來的部分就是關於撥放得相關設定

//強迫旋轉你的iDevice (這裡是橫放)
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];

 // 設定撥放器的外觀
 [WebPlayer setControlStyle:MPMovieControlStyleFullscreen];
        [WebPlayerr setFullscreen:YES];

 //設定影片比例的縮放、重複、控制列等參數

//影片旋轉90度
WebPlayer.view.transform = CGAffineTransformMakeRotation(1.5707964);
WebPlayer.scalingMode = MPMovieScalingModeAspectFit;

WebPlayer.repeatMode = MPMovieRepeatModeNone;

//將影片加至主畫面上

WebPlayer.view.frame = self.view.bounds;

[self.view addSubview:WebPlayer.view];

//開始播放
 [WebPlayer play];

這樣其實就可以撥放全螢幕的影片並且將手機橫放

如果播放完影片要可以回到原來的畫面,則要多接收一個Observer.

// 註冊endPlay 當撥放完畢的時候,會收回傳的通知

 [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(endPlay:)
                                                     name:MPMoviePlayerPlaybackDidFinishNotification
                                                   object:WebPlayer];

最後就是放endPlay的所有內容,裡面的重點在釋放撥放器與回到iDevice相關設定

-(void)endPlay: (NSNotification*)notification
{
	//解除註冊回傳
	[[NSNotificationCenter defaultCenter] removeObserver:self 	name:MPMoviePlayerPlaybackDidFinishNotification object:WebPlayer];

	//將你的iDevice 轉回來
	 [[UIApplication sharedApplication] 	setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES];

	//停止播放
	 [WebPlayer stop];
	//Release control

	[WebPlayer release];

	//現在的view 移除~ 回到原本的view
	[WebPlayer.view removeFromSuperview];

}

參考文章:

XReadr–A simple Google Reader App on Windows Phone 7

Finally, I decide to release the source code of my Windows Phone Google Reader App.

Please feel free to https://xreadr.codeplex.com/ here.

Here is my project summary:

Project Description
XReadr is a simple Windows Phone 7 app using Google Reader API.
It already has login, browse and mark it as read function here.
XReadr is simple Windows Phone 7 App which using Google Reader API.
It also has follow function:

  1. Login page which using HttpWebRequest
    XReadr.jpg
  2. Browse Unread Labels
    XReadr2.jpg
  3. Browse every news on Label
    XReadr3.jpg
    I also put the first draft of source code, I hope it could help all of you which want to write more Windows News App here.
    More implementation detail about how Windows Phone to use Google Reader API, please refer my blog here:
    http://www.evanlin.com/blog/archives/001138.html
    http://www.evanlin.com/blog/archives/001139.html
    It write by Traditional Chinese, feel free to ask me via English.

[C#][WINDOWS PHONE] 關於頁面處理的相關小細節(改變初始頁面與頁面間傳遞參數)

這幾天開始把原來的RSS Reader APP程式多加頁面後,發現了一些小問題。網路上或許還算是好找。

但是我稍微整理一下,其實Pou’s blog兩篇文章有相當清楚的解釋

在此只把常遇到的兩個問題整理一下:

  1. 如何改變初始頁面(How to change default page on Windows Phone)
    修改文件”WMAppManifest.xml”以下程式碼:
<Tasks>
  <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
</Tasks>
  1. 如何在頁面中傳遞參數(How to pass parameter over pages on Windows Phone)

在頁面間傳遞參數可以把它當成是網頁的GET模式(就是?Param_1=value_1&Param_2=value_2)

在原來的頁面可以用以下的指令傳遞

string mylogin = "/Page2.xaml";
mylogin += "?Param1=" + "VALUE1";
mylogin += "&Param2=" + "VALUE2";

if (!String.IsNullOrWhiteSpace(mylogin))
{
	this.NavigationService.Navigate(new Uri(mylogin, UriKind.Relative));
}

再接收的Page2就必須要有以下的方式去接受參數

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
            //Get parameter
            string myParam1 = NavigationContext.QueryString["Param1"];
            string myParam2 = NavigationContext.QueryString["Param2"];
}

這樣就可以了~~~

參考網頁:

[C#][Windows Phone][JSON]如何用C#完成一個簡單的Google Reader APP(下)


3. 瀏覽全部尚未閱讀的列表

接上篇文章,接下來會開始講解如何去獲得使用者所有標籤(Label)的文章。

一開始首先一樣是先提供這裡會用到的相關Google Reader API的講解

> > [https://www.google.com/reader/api/0/unread-count?allcomments=true&output=json&ck=12121&client=scroll](https://www.google.com/reader/api/0/unread-count?allcomments=true&output=json&ck=12121&client=scroll) > >

你就可以在瀏覽器上面獲得你要的資訊。你如果有登入你可能會獲得像是以下的一些資料。

接下來是取得資料的相關原始碼:

public void GetGoogleReaderUnReadCount()
        {
            string auth_params = string.Format("https://www.google.com/reader/api/0/unread-count?allcomments=true&output=json&ck=" + DateTime.Now.Ticks.ToString() + "&client=scroll");

            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(auth_params);
            httpRequest.Method = "GET";
            httpRequest.Headers["Authorization"] = "GoogleLogin auth=" + UserAuth;
            httpRequest.Headers["Cookie"] = "SID=" + UserSid;
            httpRequest.BeginGetResponse(new AsyncCallback(ResponseCallbackInner), httpRequest);
        }

抓回資料後,就開始要去parse這些資料,這邊會用到大量的JSON相關技巧,我也盡量試著解釋清楚一點給大家知道。首先,會拿到以下的資料,以下是以我的資訊當作範例~跟你拿到的可能會有點差異。

{
"max":1000,
"unreadcounts":[
	{
		"id":"user/-/label/教學網站",
		"count":9,
		"newestItemTimestampUsec":"1335595557150290"
	},
	{
		"id":"user/-/label/Funny",
		"count":83,
		"newestItemTimestampUsec":"1335621983685977"
	},
	{
		"id":"user/-/label/專業評論",
		"count":38,
		"newestItemTimestampUsec":"1335617137314302"
	}
}

這些資料就是JSON的資料,關於JSON是甚麼與JSON.NET該怎麼使用的部分,網路上有許多相關的程式碼,我這裡就不詳述了。

根據上面資料排序的結果,我們需要去抓unreadcounts下面的子結點,而他的資料格式如下:

public class ServerUnreadResult //JSON
        {
            public string id { get; set; }
            public string count { get; set; }
            public string newestItemTimestampUsec { get; set; }
        }

所以在我們程式碼中,就是可以依照以下的安排:

private void ParseUnreadList(string responseString)
        {
            //JSON Parse
            JObject googleSearch = JObject.Parse(responseString);

            // get JSON result objects into a list
            IList<JToken> results = googleSearch["unreadcounts"].Children().ToList();

            // serialize JSON results into .NET objects
            IList<ServerUnreadResult> searchResults = new List<ServerUnreadResult>();
            foreach (JToken result in results)
            {
                ServerUnreadResult searchResult = JsonConvert.DeserializeObject<ServerUnreadResult>(result.ToString());

                //Parse the label name
                // ex: user/06771113693638414260/label/Win8
                string LabelID = searchResult.id;
                string[] arrs = LabelID.Split('/');
                if (!arrs[0].Contains("user"))
                    continue;
                LabelID = arrs[3];
	// Add to Your arrary...
	.......
            }
        }

開始講解這段的程式碼,主要就是第7行的部分可以直接選取到unreadcounts子結點下面所有的內容。然後再針對所有子結點開始DeserializeObject,這樣就可以把所有資料填入到ServerUnreadResult 所產生的類別資料中。這裡主要需要的是標籤名稱與尚未讀取的文章數目。

4. 打開某個標籤(Label)內去看裡面還沒閱讀的文章

當你知道某個標籤內有多少文章,使用者就應該可以點選該標籤去看某個標籤內的所有文章。所以我們需要開始去處理如何查詢某個標籤內所有尚未閱讀的文章。

接下來的部分有點小複雜的是,因為傳回來的JSON資料會相當的多,所以可能需要一些工具去幫助你了解JSON資料。個人推薦http://json.parser.online.fr/這個網站,他可以把你JSON回傳得資料展開。可以幫助你看清楚資料裡面的階層關係。

跟之前的介紹一樣,一開始先提供相關鏈結:

> > [http://www.google.com/reader/api/0/stream/contents/user/"](http://www.google.com/reader/api/0/stream/contents/user/") + UserInfoClass.userId + "/label/"+sLabel+"?n=15&ck=" + DateTime.Now.Ticks.ToString() + "&client=scroll&format=json&xt=user/" + UserInfoClass.userId + "/state/com.google/read > >

跟之前的指令一樣你只要把UserInfoClass.userId換成你的ID還有把DateTime.Now.Ticks.ToString() 換成任何一個隨意的值。你就可以在瀏覽器上面獲得你要的資訊。這裡有一個參數要特別講解。

> > &xt=user/-/state/com.google/read > >

這個參數就是幫你把你讀過的部分去除掉,也就是挑選你”尚未閱讀的部分”。

此外另外一個參數n=15 就是顯是你要幾筆資料,你可以將前一個動作所取出來所有尚未讀取的文章放在這裡,預設值是給20。

接下來就是提供給大家相關的程式碼的部分:

public void GetATOMbyLabel(string sLabel)
        {
            string auth_params = string.Format("http://www.google.com/reader/api/0/stream/contents/user/" + UserInfoClass.userId + "/label/"+sLabel+"?n=15&ck=" + DateTime.Now.Ticks.ToString() + "&client=scroll&format=json&xt=user/" + UserInfoClass.userId + "/state/com.google/read");

            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(auth_params);
            httpRequest.Method = "GET";
            httpRequest.Headers["Authorization"] = "GoogleLogin auth=" + UserAuth;
            httpRequest.Headers["Cookie"] = "SID=" + UserSid;
            httpRequest.BeginGetResponse(new AsyncCallback(ResponseCallback), httpRequest);
        }

這邊沒有太多程式碼的部分需要說明。

接下來就要處理回傳的JSON資料,這僅僅是一筆的資料如下,由於資料有點大量,我盡量刪除不需要的部分:

{
"direction":"ltr",
"id":"user/-/label/Apple",
"title":"在 Google 閱讀器中取得 Evan Lin 的「Apple」",
"continuation":"COGG3sTqta8C",
"self":[
{
"href":"http://www.google.com/reader/api/0/stream/contents/user/-/label/Apple?nu003d15u0026cku003d2323232323u0026clientu003dscrollu0026formatu003djson"
}
],
"author":"Evan Lin",
"updated":1334555570,
"items":[
{
"id":"tag:google.com,2005:reader/item/f1c6c6aed52d2682",
"title":"【限時免費】Moco Cam:復古底片當道,LOMO 鏡頭隨你拍,超過20種濾鏡效果,原價0.99,限時免費下載中",
"alternate":[
{
"href":"http://funiphone.pixnet.net/blog/post/37297964",
"type":"text/html"
}
],
"content":{
"direction":"ltr",
"content":"u003cpu003eu003cimg srcu003d"http://pic.pimg.tw/funiphone/1334549031-3221087701_q.png" altu003d"" widthu003d"150"u003eu003cimg srcu003d"http://pic.pimg.tw/funiphone/1334549497-4194937028_n.png" altu003d"" widthu003d"450"u003eu003c/pu003enu003cpu003e u003c/pu003enu003cpu003e u003c/pu003enu003cpu003eu003ca hrefu003d"http://itunes.apple.com/app/moco-cam-camera-lens-effects/id371271476?mtu003d8"u003eu003cimg styleu003d"display:block;margin-left:auto;margin-right:auto" srcu003d"http://pic.pimg.tw/funiphone/1310632558-92007661eba0bc5e489df3d66cfff9b9.jpg?vu003d1310632559" altu003d"按此下載.jpg"u003eu003c/au003eu003c/pu003enu003cpu003eu003cimg srcu003d"http://a1.mzstatic.com/us/r1000/059/Purple/b6/38/6b/mzl.fgzqmjnx.320x480-75.jpg" altu003d"iPhone Screenshot 1" widthu003d"280"u003e u003cimg srcu003d"http://a5.mzstatic.com/us/r1000/038/Purple/ff/8a/7c/mzl.fzmsyokn.320x480-75.jpg" altu003d"iPhone Screenshot 3" widthu003d"280"u003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:14pt"u003eu003cspanu003e【目前售價:u003cspan styleu003d"color:#ff0000"u003e限時免費u003c/spanu003eu003c/spanu003eu003cspanu003e】u003c/spanu003eu003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:14pt"u003e【檔案大小:5.0 MB】u003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:large"u003eMoco Cam (Camera Lens Effects) 限時免費的好用鏡頭濾鏡軟體,這個App介面十分簡單,但支援超過20幾種濾鏡。原價0.99美金,限時免費中,喜歡用iPhone、iPad等iOS裝置照相拍照的話,可以趁限免時下載此程式App。u003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:large"u003e(下為 iTunes 上的玩家評價)u003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:large"u003eu003cimg titleu003d"89" srcu003d"http://pic.pimg.tw/funiphone/1334549972-1765202292.png" altu003d"89" borderu003d"0"u003e u003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:large;color:#0000ff"u003eFun iPhone(APP玩家)評分:★★★u003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:large"u003eu003cbru003eu003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:large"u003e此相機修圖程式的首頁介面非常簡單,其實也有點陽春。按下方咖啡色方塊可進入程式。u003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:large"u003eu003cimg srcu003d"http://a5.mzstatic.com/us/r1000/030/Purple/29/f7/f2/mzl.xxifelxh.320x480-75.jpg" altu003d"" widthu003d"320"u003eu003c/spanu003eu003c/pu003enu003cpu003eu003cspan styleu003d"font-size:large"u003e要選擇 take a photo 相機照相或直接從手機相簿中選擇想加入濾鏡的圖片u003c/spanu003eu003c/pu003e u003cdivu003eu003ca hrefu003d"http://funiphone.pixnet.net/blog/post/37297964"u003e(繼續閱讀...)u003c/au003eu003cimg srcu003d"http://pixanalytics.com/pa.gif?tu003dfront_blog_feedu0026amp;document.URLu003dhttp://funiphone.pixnet.net/blog/post/37297964"u003eu003c/divu003e"
},
"origin":{
"streamId":"feed/http://funiphone.pixnet.net/blog/feed/rss",
"title":"Fun iPhone 愛瘋玩家 (APP玩家):: 痞客邦 PIXNET ::",
"htmlUrl":"http://funiphone.pixnet.net/blog"
}
}
}

這邊資料有點多,我盡量去分開講。這裡大家會用到一些資料內容主要有以下的資料。

  • [“alternate”][“href”]: 這是這篇文章原來的網址,可以用來展開到瀏覽器用。

  • [“origin”][“streamId”]: 這個是這個feed的ID,之後在標記閱讀會用到

提供程式碼之前,一樣的我們需要把資料先宣告成類別如下:

public class ServerLabelATOMResult //JSON
        {
            public string id { get; set; }
            public string title { get; set; }
        }

        public class ServerLabelATOMResult2 //JSON
        {
            public string href { get; set; }
            public string type { get; set; }
            //public string content { get; set; }
        }

接下來就提供程式碼的部分:

private void ParseLabelATOM(string responseString)
        {
            //JSON Parse
            JObject googleSearch = JObject.Parse(responseString);

            // get JSON result objects into a list
            IList<JToken> results = googleSearch["items"].Children().ToList();

            // serialize JSON results into .NET objects
            IList<ServerLabelATOMResult> searchResults = new List<ServerLabelATOMResult>();
            foreach (JToken result in results)
            {
                ServerLabelATOMResult searchResult = JsonConvert.DeserializeObject<ServerLabelATOMResult>(result.ToString());
                string newsID = searchResult.id;
                string feedID = result["origin"]["streamId"].ToString();
                string feedTitle = result["origin"]["title"].ToString();

                ///// Get the link of this news.
                string sLink = "";
                IList<JToken> results2 = result["alternate"].Children().ToList();
                foreach (JToken result2s in results2)
                    sLink = result2s["href"].ToString();
	//Add to your data set here
            }
        }

這裡要特別講解一下,由於JSON裡面的LIST 主要是處理多個資料集(LIST)的方式,就如同對應到JSON的

> > ":[" > >

所以在這裡的[“alternate”][“href”]必須當作是多個資料,雖然Google本身也只有包了一個資料集而已,也就是說雖然Google裡面只有”href”與”http”共一個資料集(LIST)但是我們還是得這樣處理他,不然拿不到資料。這個部分也弄了很久,在此分享給大家。

5. 打開該文章網站並且將其標記已經閱讀(mark as read)

這邊的部分就請參照我之前的文章,在這裡就不再詳述了。