:::

我讓CKEditor也可錄音了:Recordmp3js插件 / Recordmp3js Plugin: Record Voice in CKEditor

我讓CKEditor也可錄音了:Recordmp3js插件 / Recordmp3js Plugin: Record Voice in CKEditor

2014-09-06_004725

我做了CKEditor的插件Recordmp3js,這是以HTML5的新功能為基礎,建構在Recordmp3js專案上實作的插件。以下介紹這個套件的功能。

I developed a CKEditor pluing: Recordmp3js. This is based on HTML5 audio function and Recordmp3js project. You can use Recordmp3js plugin to record voice in CKEditor. This article introduce Recordmp3js and some development memo.


CKEditor插件:Recordmp3js / CKEditor Plugin: Recordmp3js

recordmp3js的特色如下:

  • 使用HTML5的錄音功能,不需要Flash或Java Applet等其他插件。
  • 錄音功能旁有個音量顯示器,可以知道自己的麥克風有沒有啟用或收到聲音。
  • 限制錄音長度:最短3秒,最長60秒。
  • 錄音檔案可以壓縮成MP3,而不是預設產生WAVE。
  • MP3檔案預設以Base64編碼儲存,也可以儲存到PHP File Host專案上。

安裝說明請看專案的README

使用介紹 / Usage

2014-09-06_005312

安裝好之後會看到一個麥克風的圖示gentleface.com free icon set

2014-09-06_012542 - copy

開啟視窗之後,要先按瀏覽器的「允許」麥克風。

PicPick 2014-09-06 01-23-32 2

然後主要操作介面才能正常啟用。左邊是錄音的按鈕,右邊是音量的顯示器,未開始錄音時是以單色顯示。讓我們按下錄音按鈕。

PicPick 2014-09-06 01-00-52 1

開始錄音。你可以看到限制錄音時間,右邊的音量顯示器變成彩色了。

PicPick 2014-09-06 01-36-14 5

停止錄音之後,要等待系統轉檔與上傳。大致上錄音1分鐘就需要1分鐘轉檔。

2014-09-06_004725

轉檔完成,下面會出現音樂播放界面。按下音樂下載圖示則可以下載錄音檔MP3music_down。錄音檔案的時間長度比實際錄音的時間還要長,這是已知的正常BUG (參考Known issues那段),目前沒有解決方法。

2014-09-06_014012

按下「確定」之後,就可以在編輯器內插入<audio>標籤了。

開發感想 / Development

萬用的Base64編碼 / Amazing Base64 Encoding

2014-09-06_100638

其實前一篇開發的PHP File Host專案是為了保存這篇的錄音檔而開發,規劃上是最後才實作。不過真的摸到Recordmp3js之後,才發現原來保存二進位MP3檔案的方式竟然是用Base64編碼!

Base64編碼是一種將二進位檔案以字串的方式編碼的方法。一般HTML網頁是以純文字的方式保存,因此網頁上面的圖片、聲音檔案等二進位資料通常是另外儲存,再以<img>、<audio>標籤嵌入到HTML網頁中。可是這個動作是撰寫HTML網頁初學者的第一個難關:為什麼網頁跟圖片要分開儲存?這也造成了複製網頁檔案的困難,不能只有複製HTML網頁檔案本身,還得複製相關使用的二進位圖片檔案。

Base64編碼可以讓圖片以字串的方式保存在HTML網頁中,而不需要額外保存一個檔案。我以前也介紹過以Base64編碼保存圖片這件事情。在寫這個Recordmp3js插件時,也因為覺得還要另外找地方插入麥克風圖示很麻煩,所以直接用Base64編碼的圖片來插入。可是我還真沒想到原來Recordmp3js的MP3聲音檔案也是用Base64來儲存!

以前只是單純地使用Base64編碼的檔案,但是到這時候我才意識到Base64的麻煩之處。一般是使用file類型表單欄位來上傳檔案,例如:

<input type=”file” name=”file” />

但是由於Base64編碼是字串資料形態,所以用普通的text類型表單欄位來遞交:

<input type=”text” name=”file” />

這兩者的name雖然都是file,但是對伺服器來說卻是不一樣的。在PHP當中前者是要用$_FILES[“file”]來取用、後者是要用$_POST[“file”]。此外,由於Base64編碼並沒有指定檔案名稱,所以還需要用另一個text欄位來傳送檔案名稱。

而即使Base64編碼是字串形式,也不能用JSONP的方式來做跨網域傳輸。因為JSONP實際上是將資料輸入在網址上,而Base64編碼的結果通常很容易超過網址的2083字元限制

這造成我得改寫PHP File Host的檔案接收方式,又花了我一番功夫。到最後索性乾脆讓Recordmp3js預設使用Base64編碼來儲存,讓PHP File Host變成選擇性支援。雖然這會造成插入CKEditor的資料變得超級長,但不需要額外架設伺服器保存MP3檔案這點還是蠻容易讓人使用的。

MP3轉檔 / MP3 Convert

一開始研究HTML5錄音功能時,最讓我困擾的地方在於HTML5預設的錄音結果是WAVE格式。WAVE是沒有壓縮的聲音檔案,因此聲音檔案的大小非常大,讓我難以直接使用HTML5的錄音功能來儲存錄音檔案。

本來還在考慮是否要在PHP File Host加上檔案轉檔功能,在上傳檔案之後轉檔成MP3或amr格式。可是後來意外發現Recordmp3js居然在Recorderjs專案之上加上了MP3轉檔libmp3lame.js的功能,讓MP3轉檔的工作直接就在客戶端瀏覽器上完成。這真的是太方便了。

當然,對很多網頁開發者來說,這是風險很高的事情。因為客戶端使用的瀏覽器跟電腦效能不一,因此完全不能寄望IE6或是在行動裝置上的瀏覽器能夠正常執行。我剛剛拿了Android的Chrome跟Firefox來玩玩看,的確是無法開啟。

不過我的應用場景比較特殊,我可以要求使用者以Chrome或Firefox來使用我的系統,這個顧慮就暫時不在我的考量之中。

其他的轉檔格式? / Other Better Audio Format?

這也讓我想到是否可能用更有效率的amr格式來為語音聲音檔案編碼,赫然發現GitHub上的確有amr.js專案,真是厲害。然而選用編碼格式也要顧慮到瀏覽器的支援,根據w3schools.com的HTLM5 Audio介紹,<audio>標籤只支援MP3、Wav跟Ogg格式,大部分瀏覽器都支援MP3,除了Opera。支援細節如下:

Browser MP3 Wav Ogg
Internet Explorer YES NO NO
Chrome YES YES YES
Firefox YES YES YES
Safari YES YES NO
Opera NO YES YES

 

HTML5的錄音元件 / Audio in HTML5

Recorderjs將HTML5的錄音元件包裝的非常好用,但是實際上使用之前,還是需要經過非常多的設定。你可以看看Recordmp3js的範例網頁程式碼,JavaScript設定那邊就一長串了,一開始研究的時候還真讓人感到困擾。Recordermp3js也具備了錄音完成之後上傳的功能,可是這功能卻寫死在Recordmp3js檔案裡面,而非開放設定的功能,讓我到最後還跑到Recordmp3js裡面去研究,也花了不少功夫。

在研究的過程中,越來越覺得audio真是有趣的應用。藉由結合多個音訊來源,我們可以動態控制各種聲音播放,就可以自行製作各種樂器。Web Audio Demos展示了很多聲音的應用,Web Audio Vocoder是其中一種強調混音的功能,這激起了很多不同應用的可能性。而我則是參考了AudioRecorer華麗的音量顯示器,做到Recordmp3js當中,讓錄音介面感覺漂亮一點。

錄音功能需要的Worker / Recorder and Worker

使用HTML5錄音跟MP3轉檔時,Recordmp3js都使用到了HTML5新元件Worker。一般來說,這個Worker必須是獨立的JavaScript程式碼,而且受限於同網域下執行的安全性問題。在跨網域應用中,這是一個很大的門檻。

但是我參考使用web workers這篇文章的說明,撰寫了worker_manger.js,將worker要執行的程式碼事先插入到目標網頁中,然後在以該網頁上的worker程式碼作為worker物件執行,就能夠保持在同網域執行的限制,迴避跨網域的問題。

雖然這個小功能我只用了很短的時間來做,但其實應該對很多人來說是很重要的功能吧?有機會再來正式發佈好了。

如何允許瀏覽器錄音 / How to Allow Browser Enable Microphone

使用HTML5錄音元件的另一個重點在於「允許」錄音檔案的事件。實際上啟用Recordmp3js的時候,跟HTML5元件宣告我要使用麥克風的時候,不是所有的瀏覽器就會跳出提示問你要不要啟用麥克風。

Firefox會在使用時直接跳出是否允許啟用,一個網頁只會問一次,Chrome有些版本也是如此。但是我電腦的Chrome卻不會在Recordmp3js載入時跳出來詢問,而是要離開網頁、再回到網頁時才會詢問。我索性加入一個<iframe>標籤,讓網頁觸發讀取事件,好讓Chrome問我要不要允許使用麥克風。但是離開網頁又回來時,Chrome還是會問我要不要允許麥克風,還好這動作也只要問一次而已。

很多使用者應該會忘記做「允許」麥克風這個動作。Chrome跟Firefox的介面都不太容易讓人理解,我可以預期這個動作應該是最讓人感到困擾的地方吧。

播放介面與<audio>標籤 / Audio Controller <audio> Tag

至於播放介面,我就直接使用HTML5的<audio>標籤。雖然<audio>標籤提供了播放/暫停、時間、播放進度條、聲音控制等功能,但是各個瀏覽器上<audio>長得都不太一樣,因此網路上大多建議是自行重寫<audio>的操作介面。但想到這個<audio>是要插入到CKEditor當中使用,寫得太複雜也不利於編輯。所以我還是選用最基本的<audio>標籤來顯示。

CKEditor插件開發 / About CKEditor Plugin Development

最後來講講CKEditor插件的開發。

一開始我是看为CKEditor在线编辑器增加一个自定义插件這篇,一步一步來實際操作看看。但是做到最後並沒有如期地做出可以用的CKEditor插件。我也去翻了CKEditor的Plugin教學跟它的API,但後來還是覺得乾脆直接複製既有的Plugin開始做起好了,所以就打開被壓縮的程式碼來看,直接從可以運作的功能中找尋我需要的程式片段。

雖然並不是什麼正規的學習方式,但這樣也在一片混亂中寫完了這個插件。有多混亂呢,看看插件的程式碼就知道了orz

總之最後還是完成了,也發佈到CKEditor的Add-on頁面去,也算是對這份研究有個交待啦!

話說回來,一開始會全部都重頭製作的原因就是因為在CKEditor與TinyMCE上找不到這種錄音的插件。現在我可以用這種方式來製作錄音插件的話,那其實像是webcam拍照與錄影等各種應用應該都沒問題才是。有機會再來研究看看吧。

(more...)

如何閱讀JavaScript/CSS壓縮程式碼?快使用程式碼格式化工具 / How to Maxify/Parsing/Format Minified Code

如何閱讀JavaScript/CSS壓縮程式碼?快使用程式碼格式化工具 / How to Maxify/Parsing/Format Minified Code

image

為了閱讀被壓縮(minify)的JavaScript與CSS程式碼,我們可以使用線上工具Code Formatter或是NetBeans的format指令來為程式碼進行排版。

You can use some tools to maxify/parse/format the minified JavaScript or CSS codes, for example, Online Code Formatter or NetBeans.


關於壓縮程式碼 / Minify Code

JavaScript與CSS程式碼的特性在於必須下載到使用者客戶端才能執行,因此降低程式碼的大小是很常見的方式。JavaScript跟CSS通常是以壓縮(minify)的形態發佈給大家使用。被壓縮的程式碼檔案名稱通常會加上「.min」,而原始碼通常會加上「.src」,舉例來說:

image

這是jQuery 1.11.1原始碼的樣子。檔案大小是276KB。

image

這是jQuery 1.11.1壓縮程式碼的樣子。檔案大小是93.5KB,幾乎是原始碼的1/3大小。

壓縮程式碼中會移除註解、刪除空白與換行、縮短變數名稱(例如變數用了var book,會縮短成var a)。我之前也介紹過使用YUI CompressorMinify壓縮程式碼的方法。而現在壓縮JavaScript跟CSS已經是主流用法,像是Fat-Free Framework中也直接內建了壓縮工具,非常方便。

為什麼要閱讀被壓縮的程式碼? / To Read Minified Code

雖然像是jQuery這種知名的函式庫會提供非壓縮的原始碼供大家閱讀研究,但是還是很多專案並沒有提供解壓縮的原始碼,而只有被壓縮的程式碼可以看。

我最近在研究如何撰寫CKeditor的plugin,可惜他的教學跟文件寫的並不是很好。後來我覺得比起研究文件,不如直接修改程式碼,說不定還比較快。

2014-09-05_164627

可惜的是,大部分CKeditor中plugin的程式碼都是壓縮後的結果,閱讀起來不太容易,我們需要一些解壓縮(maxify)工具來輔助我們閱讀這些程式碼。

在此介紹兩種格式化被壓縮程式碼的方便工具:NetBeans的format指令跟線上工具


NetBeans的格式化指令 / “Format” in NetBeans

我使用的是NetBeansIDE 8.0。要格式化被壓縮的JavaScript程式碼的做法如下:

  1. 開啟JavaScript檔案
    2014-09-05_170730
  2. 開啟Source > Format 
    2014-09-05_170801
  3. 變成了漂亮的排版
    2014-09-05_170855

不過你可以注意到下面還是有一團程式碼沒有解壓縮到,這似乎是NetBeans的限制。此外,NetBeans也不能解壓縮CSS程式碼,使用範圍有限。

使用Code Formatter解壓縮 / Maxify Code on Online Code Formatter

這個工具名稱叫做「Format, Beautify, Maxify, Unpack or Deobfuscate JavaScript/jQuery/HTML/JSON/CSS Codes」,有點長,還是用網址上的Code Formatter來稱呼好了。

image

這工具用法很簡單。首先先把壓縮的程式碼貼在框框中,然後按下下面的按鈕「Click here to Format/Beautify/Maxify Your JavaScript/jQuery/JSON//HTML Codes」。

image

程式碼就以漂亮的版面排版好了,而且NetBeans沒解開的後面部分也排版的漂漂亮亮,這樣就能夠更輕易地閱讀程式碼了,真是令人開心呢。

希望這些工具能夠幫助程式開發者更容易閱讀程式碼。學程式的第一步就是模仿別人怎麼寫,加油!

(more...)

PHP File Host 檔案上傳專案 / PHP File Host Project

PHP File Host 檔案上傳專案 / PHP File Host Project

圖片1

最近我完成了一個用PHP做的檔案上傳專案「PHP File Host」,順便學習了PHP框架Fat-Free Framework、PHP資料庫函式庫RedBeanPHP、前端檔案上傳工具jQuery File Upload跟前端界面Bootstrap等技術。以下說明這個專案內容。

I wrote a PHP project “PHP File Host” for cross origin file uploading. In this project, I try some new technology include Fat-Free Framework, RedBeanPHP, Bootstrap and jQuery File Upload. Following is introduction of this project.


專案由來 / Project Introduction

原本我的KALS專案並不具備檔案上傳功能(其實一開始規劃時有啦,但是一直沒有實作),但最近開始有了這方面的需求。然而檔案上傳乍聽之下很簡單,但是在跨網域(Cross Origin)的情境中,卻不太容易實作。

另一方面,簡單的檔案上傳應用實作常常會有幾個問題:

  1. 實體檔案管理的問題:檔案存放在哪哩?伺服器空間足夠嗎?
  2. 檔案重複問題:如何有效率地降低檔案的使用空間?
  3. 檔案名稱問題:遇到不支援的檔案名稱編碼,存到伺服器的檔案系統時會造成亂碼的問題。

因此我想要做一個簡單的檔案上傳應用網站。這個只做一件事情:支援跨網域的檔案上傳、然後的到一個下載網址。這樣就夠了。這就是PHP File Host的由來。

專案內容 / Project

圖片2

我把最近對PHP File Host的報告彙整成為一個投影片,裡面有簡單的功能介紹:

特色 / Features

PHP File Host的特色在於:

  • 運作環境:以PHP架設,資料庫預設使用SQLite,但是不需要額外配置資料庫。
  • 跨網域檔案上傳:支援以JSONP上傳jQuery File Upload上傳
  • 避免儲存重複檔案:以MD5特徵碼來辨識檔案內容,避免儲存相同檔案。
  • 完整保留檔案名稱:以資料庫儲存檔案名稱,並由程式負責從header指定下載檔案名稱,因此不會下載到亂碼的檔名。

相關技術 / Technology

裡面主要用到幾種技術,在此我也聊一下使用這些技術的心得。

Fat-Free Framework (F3)

Fat-Free Framework (F3)是一個PHP框架。不過在講F3之前,我想先聊一下CodeIgniter。

在開發KALS時,我主要使用的PHP框架是CodeIgniter (CI)。CI大量參考Ruby on Rails的理念,大量遵守「約定優於配置」(convention over configuration)的準則。特別是對於routing功能來說,要連到指定網址就得在特定的檔案結構中撰寫相對應的PHP類別。

一開始我覺得這也不錯,大家的都能遵守約定的話,開發就能夠維持一致性。但事實上是為了這這個約定,CI限制了大量的靈活性。常常會發現要接手專案的新手要花很多時間來瞭解routing的邏輯,而且無法自由指定routing中的變數與類別也很令人覺得限制很大。最致命的就是不能支援JSONP的呼叫模式,難以跟jQuery.getJSON()搭配運用。

雖然KALS的CI被我大改之後變得可以支援JSONP,但我不覺得這是一種理想的做法。所以當我這次要開發這個專門支援跨網域檔案上傳的PHP File Host時,我就毅然決然換了另一個PHP框架。

我花了一點時間嘗試不同的PHP框架,不過後來找到了F3。這個專案特色是檔案看起來不會太複雜,特別是與龐大的CodeIgniter相比。

image

F3一些零星的功能不多,但是主要功能卻比CI好用很多。

F3的routing是由設定檔控制,寫法跟Node.js的express框架很像。這符合我們一般使用的概念:從URI追溯檔案位置。而不是像CI那樣,得先瞭解約定才能知道檔案的位置。使用配置設定來規範routing這點看起來像是違反了「約定優於配置」,但是從另一個角度來看,這也是讓「使用者」(利用URI使用系統)跟「開發者」(使用伺服器上的檔案配置)脫鉤的一種好方法。CI那種routing規範實在是太過糾結,用起來綁手綁腳的。

而F3的routing也支援分辨GET (查詢)、POST (新增)、PUT (更新)、DELETE (刪除)等REST API會使用的四種方法。不過要注意到,若針對同一URI使用GET跟POST等多種方法,最後變數只會取得使用GET這個而已。這是比較令人困擾的地方,我得再研究看看。

此外,我喜歡F3用擴增HTML標籤的方式來建立樣板,輸出的樣板能夠直接指定MIME Type為JavaScript這點也很不錯,這對JSONP支援良好,也可以輕易使用現在流行的Markdown程式語言。相較之下,CI的樣板只能說是原始人。不過F3預設限制「同源使用」(same-origin),為此得額外宣告以下header才行讓其他網站跨網域開啟F3專案:

header('X-Frame-Options: ');

CI提供了大量零星的函式(helper),讓我們能夠簡單地處理很多小東西。F3並沒有這麼多helper,但是它把很多常用的系統與環境資訊都寫在框架的系統變數裡面。習慣之後也還算好用,但我比較喜歡helper的函式形式。

在資料庫的使用上,F3的資料庫也跟CodeIgniter的Active Record一樣,都是使用ORM (Object-Relation Mapping)的方式操作資料庫。而F3多了一些NoSQL資料庫的支援,像是MongoDBJig

雖然這些ORM用起來不錯,但是我這次更想使用另一種資料庫函式庫更感興趣,那就是RedBeanPHP。

RedBeanPHP

RedBeanPHP是一個PHP資料庫函式庫,使用時只要導入它一個PHP主要檔案即可。

他在使用上跟很多ORM函式庫一樣,可以把資料表當作一個類別,裡面的一列當作是一個物件來使用。但是最大的差別在於,RedBeanPHP是不需要預先設定資料表(schemaless)的架構。

舉例來說,今天我們有一種類別叫做Book,那我們就用RedBeanPHP建立一個類別叫做「Book」的物件,然後設定其中的屬性「title」跟「author」後儲存,這樣子資料庫中就會自動幫我們把相關的table與field都設定好,連field的資料形態都會與物件屬性的形態直接相對應。

未來如果這個Book想要增加第三種屬性「price」,那就在程式中加入「price」,儲存,這樣子資料表就會多一個price的欄位。

這樣子的好處在於,我們不需要在配置程式碼之餘還要煩惱如何配置資料庫。RedBeanPHP預設採用SQLite,但也可以支援主流的關聯式資料庫,如PostgreSQL跟MySQL。

我使用RedBeanPHP在PHP File Host中儲存檔案資料,操作起來非常容易上手,而且令人驚訝地好用。

有人抱怨RedBeanPHP的資料庫查詢速度過慢,這點可能要謹慎評估。但PHP File Host少量應用看來是沒有這個問題。

Bootstrap

這次我也一併改進了前端的界面。跟以往一樣,比起重頭開始設計網頁界面,我比較偏好從既有的網頁範本開始修改。難得這次機會,我也就從知名的客戶端技術Bootstrap的範本Landing Page開始改起。

使用Bootstrap的目的包括:

  • 支援RWD (Responsive Web Design):不論電腦、平板、手機等不同螢幕大小的裝置,網頁都應該自動最佳化調整版面。這點可以靠Bootstrap的Grid system來調整。
  • 一致且美觀的元件:Bootstrap的選單、按鈕、讀取條非常好看。我還蠻喜歡它的Default、Primary、Success、Info、Warning、Danger、Link的通用分類與對應顏色。
    image
  • 豐富的圖示:不光是Bootstrap本身提供了大量的圖示(Glyphicons),Landing Page範本還用了更多元的Font Awesome圖示,基本功能操作真的是不需要額外在準備其他圖片了。

圖片1

最後完成的結果在Am I Responsive?上看起來就是這樣,開頭的圖片會按照視窗畫面去做調整,頂端選單列也會在小螢幕中自動縮成一個按鈕,成果很不錯。

雖然我老是做一些伺服器端的專案,但是作為網頁相關的程式設計師,前端界面技術自然也不能生疏。PHP File Host雖然只是一個小小的網站,但是做起來還是令我挺開心的。

jQuery File Upload

我這次也加入了jQuery File Upload來改善檔案上傳的介面。這個套件可以用簡單的方式來設定檔案上傳的功能,讓我們輕易加入以下功能:

  • 點選按鈕、選擇檔案、馬上上傳
  • 上傳進度條
  • 拖曳至指定區域上傳
  • 剪貼上傳

我很喜歡這些方便的操作,傳統點選檔案按鈕的方式實在是太過麻煩。

另一方面,我本來還蠻煩惱怎麼用jQuery File Upload來進行跨網域傳送檔案,卻意外發現jQuery File Upload使用了HTML5元件postMessage來傳輸檔案的方式,比我以前提出的JSONP跨網域檔案上傳還要好用很多,真讓我驚豔。

不過最後我要在其他專案使用jQuery File Upload設定上傳功能時,卻發現它使用的是jQuery 1.11,與KALS專案的jQuery 1.4有很大的差別。加上jQuery File Upload也要使用jQuery UI等工具,導致它與其他功能互相衝突,最後我還是放棄在KALS專案使用jQuery File Upload而使用原本的JSONP跨網域檔案上傳方式。

向DSpace致敬 / Salute to DSpace

最後也提一下PHP File Host內部檔案儲存的方式,這部分我大量地參考了DSpace保存檔案的方式。

DSpace依照檔案的MD5特徵碼作為檔案名稱與實體位置的設定,因此每個檔案都長得像是「01f7b24e629cc23e369983994d0b8fbe」。檔案的名稱、MIME Type等相關資訊則是寫在資料庫中,連同上傳者、上傳時間等操作記錄也一併分開儲存。

這樣做可以改善檔案重複儲存、避免檔案名稱編碼不支援等問題,但是檔案管理 (特別是刪除)跟下載就成為另一個技術上的重點。目前PHP File Host還沒有做的刪除功能,就只是一直擺放資料,然後以供人下載而已。

利用Base56面碼縮短網址 / Shorten URL by Base56 Encoding

喔對了,為了避免網址過長,我還特別用了Base56將數字ID以「0123456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ_-.~」等網址允許的字元進行編碼。即使檔案的編號很大,網址長度仍然不會很誇張地漲大。這種做法我也挺喜歡的。

這些大致上就是PHP File Host使用到的技術。


結語:過時的技術? / Conclusion: Outdated Technology?

剛好最近也看到一篇分析報導:「AngelList 分析:越好的公司越喜歡用 Python,越差的公司越愛用 PHP」。該分析將公司分成Okay、Good、Great三級,然後看公司使用的程式語言。

其中伺服器端PHP排行第三、客戶端Bootstrap排行第五(但是RoR我不認為是客戶端技術)、資料庫SQLite榜上無名。雖然直接看圖表起來也沒啥不好,但我現在才學這些技術,的確是比很多人慢了許多。

之後有機會的話,我想要研究伺服器端的Node.js,然後在單一頁面應用上繼續精進AngularJS (之前寫了一個批次開啟網頁的小應用,蠻好上手的)。久違地學習新的技術,真的很令人開心呢。

(more...)

為何Power Point插入圖片變得模糊了?勾選不要壓縮檔案中的影像 / Disable Power Point’s Image Compression Configuration to Avoid Blurring Images

布丁布丁吃布丁

為何Power Point插入圖片變得模糊了?勾選不要壓縮檔案中的影像 / Disable Power Point’s Image Compression Configuration to Avoid Blurring Images

2014-09-03_095441

如果你在Power Point插入圖片時,發現圖片變得模糊不堪使用,那就得啟用選項中的「不要壓縮檔案中的影像」來避免這個問題。

In Power Point, if you get a blurred image after inserting it, you should enable “Do Not Compress Images in File” at Power Point Options.


圖片模糊的問題 / Problem when Inserting Images

本文使用的是Power Point 2013,不過我在Power Point 2010上也會遇到相同的問題。

image

在做投影片的時候使用插入圖片時……

2014-09-03_095417

插入一張電腦截圖,可是圖片卻很小。

2014-09-03_095441

圖片放大之後模糊不堪使用。

網路上找了以下,從plumdumplings的回答中才知道原來是因為Power Point啟用了圖片壓縮的緣故。以下說明解法。

解決方法 / Solution

  1. 開啟Power Point的選項
    image
    image
  2. 到「進階」中,取消勾選「捨棄編輯資料」,並勾選「不要壓縮檔案中的影像」。
    2014-09-03_095557

這樣子重新插入圖片時,圖片解析度就不會被壓縮了。

2014-09-03_095642

這問題困擾了我好一陣子,不過網路上好像很少看到有人提起。在此跟大家分享。

(more...)

Git合作開發從NetBeans開始!NetBeans複製git專案教學 / Clone Git Project in NetBeans

Git合作開發從NetBeans開始!NetBeans複製git專案教學 / Clone Git Project in NetBeans

2014-08-18_154048

本文介紹如何在NetBeans中複製Git專案到本機端,然後建立NetBeans專案,以便開始進行程式的開發。

This article describes how to clone Git project and then create a NetBeans project in NetBeans.

Git專案 / Git Project

2014-08-18_152111 - Copy

本文以我最近要開始的新專案「PHP File Host」為例子來做示範。這是一個存放在GitHub的開放原始碼專案,大家可以任意複製(Clone)裡面的程式碼到本機端來修改。要複製Git專案的方法很多,有HTTPS、SSH與Subversion等通訊協定。在NetBeans裡面,我們可以用HTTPS通訊協定來進行複製,連線方式在GitHub專案網頁的右方下面「HTTPS clone URL」。

總結上述,以下是Git專案的資訊:

NetBeans環境 / NetBeans Version

2014-08-18_152321

NetBeans是我現在主要的IDE開發環境,他也是一個開放原始碼的自由軟體。NetBeans不僅支援語法標亮、自動完成(auto-completion),從7.4版之後也開始支援Git。以往我使用TotoiseGIT來管理GIT的工作,現在逐漸都改以NetBeans來進行操作。

為了讓大家能夠更輕易以NetBeans來開始使用Git專案,本文將介紹如何複製Git專案到NetBeans中,並直接建立一個NetBeans專案來使用。


在NetBeans中複製Git專案 / Clone Git Project in NetBeans

以下介紹如何在NetBeans中複製Git專案。大致上操作步驟分成兩個部分:從Git複製專案檔案、以及在NetBeans中建立NetBeans專案。

Git專案主要負責程式碼的版本控制,NetBeans專案通常還包括一些專案程式碼指定編碼、伺服器上傳連線等資訊,而這些資訊並不建議放到Git專案中公開,兩者要分開處理。

Part 1. 複製Git專案 / Clone Git Project

2014-08-18_152403

在NetBeans中,請進入Team > Git > Clone…

2014-08-18_152450 - Copy

接著會開啟Clone Repository對話視窗。在這裡我們先進行Remote Repository設定。要輸入的欄位包括:

  • Repository URL: 請輸入剛剛的HTTPS複製網址「https://github.com/pulipulichen/php-file-host.git
  • UserPassword登入GitHub的身份認證。
  • Clone into:存放專案的目錄。NetBeans會在這個目錄底下再建立一個Git專案的目錄。舉例來說,我的XAMPP網頁擺在「D:\xampp\htdocs」,那麼Git專案就會出現在「D:\xampp\htdocs\php-file-host」底下。

2014-08-18_152557 - Copy

接下來選擇要複製的Remote Branches。一般是選擇該專案的代表master分支即可。直接按「Next >」按鈕吧。

2014-08-18_152609 - Copy

然後最後是確定目標資料夾 Destination Directory。這邊會帶入剛剛的設定,只要按「Finish」按鈕完成即可。

2014-08-18_152634 - Copy

複製完成之後,NetBeans會問你是否要建立NetBeans專案。打勾「Open Sources in Favorites」,然後按下「Create Project…」,接下來就進入新增專案的步驟。

Part 2. 新增NetBeans專案 / Create NetBeans Project

2014-08-18_152648

NetBeans會顯示「Net Project」對話視窗。在這邊我們要選擇與該專案相對應的程式語言類型。PHP File Host是一個PHP程式語言的專案,而且已經有Git專案過來的檔案,因此我在PHP目錄底下選擇專案類型「PHP Application with Existing Sources」。

然後按下「Next >」按鈕進入下一步。

2014-08-18_152739

在Name and Location這邊要設定的東西蠻多的。

首先我們要指定Sources Folder,請設定剛剛跟Git專案複製的目標資料夾路徑「D:\xampp\htdocs\php-file-host」。接著NetBeans會自動帶入下面的資訊。

接著我們要確認Default Encoding為UTF-8。如果沒有設定NetBeans專案的話,NetBeans會用非UTF-8的編碼來開啟檔案,造成檔案看起來會是亂碼。

然後請打勾「Put NetBeans metadata into a separate directory」,然後指定另一個地方存放NetBeans專案的資訊,不要跟Git專案擺在同一個地方。這是為了避免NetBeans專案資訊被納入Git版本控制之中,這個動作很重要。

2014-08-18_152810

最後就是運作環境設定 Run Configuration。由於我的專案會先在本機端的XAMPP底下運作測試,所以設定Run As: Local Web Site即可。如果你實際運作的伺服器在遠端,那也可以在此步驟設定遠端伺服器的連線方式。不過遠端伺服器設定比較複雜,在此就先不說明。

其他沒有特別要設定的地方,按下「Finish」完成。

2014-08-18_152833 - Copy

NetBeans會顯示剛剛設定的php-file-host專案,複製Git專案的工作就大功告成囉。

其他的Git操作 / How to use Git in NetBeans

當然,除了clone (複製)之外,NetBeans也支援很多Git的操作動作。以下舉例來說常用的指令與其位置:

  • commit: Team > commit ,我還特地設了熱鍵Alt+C,讓自己更方便就能commit
    2014-08-18_172652
  • Pull & Push: Team > Remote > Pull or Push
    2014-08-18_172709
  • 比較檔案差異 Diff: Team > Diff > Diff To…  (可以取代「Git取代分支檔案的方法」一文中以TortoiseGIT的操作動作)
    2014-08-18_172722

Git詳細的說明請參考「Using Git Support in NetBeans IDE」一文。我也還在持續摸索中,有任何心得歡迎在下面討論喔。


結語:IDE的重要性 / Conclusion: The Importance of IDE

以前常常會聽到有人會以「只要筆記本(notepad)就可以寫網頁」來當作自豪的特技,我覺得這只能說是程式設計師的基本,只能拿來跟外行人炫耀。但是如果要往更進階前進,你就必須學習使用IDE。

就目前為止,我主要使用的IDE有Aptana Studio 2 (第三版是是完全不同的東西)跟NetBeans,在我工作中,這些IDE有幾個我非常仰賴的重要工具:

  • 全文搜尋(full text search):當我要找某個函式要如何使用時,全文搜尋是很重要的。特別是像NetBeans能夠解讀程式碼,可以在你使用函式時顯示對應的註解說明,這個功能在閱讀程式(trace code)是非常好用的輔助工具。
  • 正規表達式(regular expression)的搜尋與取代:當要取代換行、找尋某個函式的使用處的時候,正規表達式非常重要。
  • 自動完成(auto-completion):有了語法自動完成,你就不用煩惱每次都為函式或變數少打一個字而帶來的bug。
  • 程式導航(navigation or outline):像是地圖一樣地顯示程式的組成,這在檢視大程式的時候十分有用。
  • Git版本控制功能:一個不做版本控制的專案不僅無法持久發展,也很難跟別人協同開發。

因此我會建議每一位致力於寫程式的朋友,請務必要熟悉一些好用的IDE。如果你跟我一樣是寫PHP與JavaScript,那我建議你就從NetBeans開始吧。

(more...)

讓ownCloud站在NAS的肩膀上!ownCloud使用者資料整合NFS的規劃 / How to Integrate NAS into ownCloud with NFS

布丁布丁吃布丁

讓ownCloud站在NAS的肩膀上!ownCloud使用者資料整合NFS的規劃 / How to Integrate NAS into ownCloud with NFS

2014-08-17_203555

本文描述如何在以OpenVZ虛擬機器架設的ownCloud 7.0.1中掛載NFS網路硬碟。文末也提供可掛載NFS的ownCloud 7.0.1版OpenVZ虛擬應用範本供大家下載安裝。

This article show you how to mount NFS in OpenVZ container's ownCloud 7.0.1. I also provided an OpenVZ virtual appliance template with ownCloud version 7.0.1 in this article.


為什麼要整合NAS? / Why ownCloud have to Integrate NAS?

我的ownCloud是以OpenVZ虛擬應用範本架設在Proxmox VE上。為了備份的方便,我傾向於每一臺虛擬機器都只保存應用程式本身,而使用者的資料──特別是像ownCloud這種會讓使用者上傳大量資料的情境,更應該要把虛擬機器跟使用者的資料分開備份。

在此考量下,Proxmox VE給每個虛擬機器的空間並不多,通常我只設8GB。而其他的資料則是透過NFS (Network File System)連線保存在NAS (Network Attached Storage)上,讓NAS的硬碟空間能夠有效利用。

ownCloud掛載NFS教學 / How to Mount NFS in ownCloud

ownCloud在第7版之後,因為調整了目錄權限檢查,所以讓NFS掛載變得很簡單。以下我以ownCloud 7.0.1的OpenVZ虛擬應用範本FreeNAS提供的NFS為例,描述如何在ownCloud中掛載NFS網路硬碟。

本範例中,ownCloud虛擬機器資訊如下:

FreeNAS的資訊如下:

  • IP是192.168.11.75
  • 開放了NFS功能,細節請看「開啟FreeNAS的NFS功能」,開放目錄為
    /mnt/dlll-cias-nas/owncloud
  • 服務連線允許ownCloud虛擬機器連線
  • 與ownCloud虛擬機器置於同一個網路中
Step 1. 啟用OpenVZ虛擬機器的NFS設定 / Enable Container’s NFS Configuration

2014-08-17_161650

為了讓ownCloud能夠掛載NFS,我們要先修改虛擬機器本身的設定。詳細做法請見「OpenVZ掛載NFS的虛擬機器設定」一文,以下摘錄重點。

  1. 把虛擬機器關機
  2. 進入節點的Shell
  3. 輸入指令: (紅字部分為VMID,請自行換成你虛擬機器的VMID)
    # vzctl set 103 –features "nfs:on " --save; vzctl start 103

等待ownCloud虛擬機器開完機之後,再來到ownCloud虛擬機器裡面操作吧。

Step 2. 安裝NFS套件 / Install NFS Tools

2014-08-17_142802

以下動作都是在ownCloud本機上的操作。

Trunkey Linux的ownCloud預設並沒有安裝連線NFS所需要的工具,我們必須先用apt-get安裝nfs-common:

# apt-get install -y nfs-common

然後切換到ownCloud的目錄:

# cd /var/www/owncloud

以下操作都在ownCloud目錄底下進行。

Step 3. 存放使用者資料到NAS / Copy Users’ Data To NAS

※ 如果不需要備份使用者資料,這一步驟可以省略。

建立暫存用的資料夾:

# mkdir data.tmp

掛載NFS目錄到暫存資料夾:

# mount -t nfs 192.168.11.75:/mnt/dlll-cias-nas/owncloud /var/www/owncloud/data.tmp

複製data資料到暫存資料夾,表示將資料存到NAS中:

# cp data/* data.tmp

取消暫存資料夾的掛載,然後移除暫存資料夾:

# umount data.tmp; rm -rf data.tmp

接下來就要正式掛載到data資料夾上了。

Step 4. 掛載NFS目錄 / Mount NFS

用mount指令掛載NFS目錄到data上:

# mount -t nfs 192.168.11.75:/mnt/dlll-cias-nas/owncloud /var/www/owncloud/data

產生必要的檔案,並且設定權限:

# touch data/.ocdata

# chown -R www-data:www-data data

特別是產生.ocdata這個檔案。如果缺乏這個動作,ownCloud網頁就會顯示錯誤訊息:

Data directory (/var/www/owncloud/data) is invalid

Please check that the data directory contains a file ".ocdata" in its root.

2014-08-17_163040

然後開啟ownCloud網頁界面。如果沒有備份使用者資料的話,原本使用者上傳的資料就會消失,但ownCloud還是可以正常運作。

Step 5. 設定開機自動掛載NFS / Mount NFS When System Start

確認NFS可以正常掛載之後,接下來就是設定開機時自動掛載。

我們以nano編輯器修改開機設定檔案:/etc/rc.local

# nano /etc/rc.local

2014-08-17_163127 - Copy

在exit 0之前加入剛剛的mount指令:

mount -t nfs 192.168.11.75:/mnt/dlll-cias-nas/owncloud /var/www/owncloud/data

存檔離開。

接著我們重新開機來測試是否有順利掛載:

# reboot

重新開機之後,以df指令檢查NFS是否順利掛載:

# df

2014-08-17_220301

你可以看到/var/www/owncloud/data已經掛載了NFS網路硬碟。

ownCloud 6備註:需要修改權限檢查功能 / ownCloud 6 Memo: How to Disable Permission Check

如果你是ownCloud第6版,那還要額外修改檢查目錄權限的程式。

由於掛載NFS時,掛載目錄的權限會直接開啟為777。在ownCloud 6當中會限制使用者資料夾data的權限只能為770,這與NFS掛載的限制相衝突。

解決這個衝突的做法是修改ownCloud的使用者目錄權限檢查程式util.php,程式碼的位置是:

/var/www/owncloud/lib/private/util.php

2014-08-17_144229

找到「public static function checkDataDirectoryPermissions($dataDirectory)」這一行,然後在「$errors = array();」之後加入「return $errors;」

這樣就能夠略過權限檢查,順利掛載NFS了。

在ownCloud 7中沒有這個問題,可以直接掛載。


ownCloud 7.0.1虛擬應用範本下載 / ownCloud 7.0.1 Virtual Appliance Download

為了方便大家使用,我把可以掛載NFS的ownCloud 7.0.1提供大家下載。這是與「ownCloud終於可以上傳中文檔案!升級ownCloud版本到7.01」一文相同的OpenVZ虛擬應用範本,請使用Proxmox VE來安裝,細節可以參考「Proxmox VE上傳虛擬應用範本」一文。

以下是管理資訊,預設密碼都是password:

  • ownCloud的管理者為 admin ,密碼為 password 。
  • Linux系統管理者為 root ,密碼為 password。
  • MySQL帳號為 owncloud ,密碼為 password。

如果要掛載NFS的話,請修改 /etc/rc.local :

2014-08-17_221700

請把mount指令前的「#」移除掉,然後設定你NFS伺服器的IP位置與NFS目錄即可。

大家使用時有什麼問題,歡迎在下面留言處討論。

(more...)