[07-24] 基于Picasa、PHP、AJAX的图片REST架构的简单实现 完结篇

一如既往的前情提要:

现在,服务器端的架设终于全部结束了,我们可以向服务器端同一个URL发送不同的Header请求,从而得到不同的反馈,REST简单说来也就是这么一回事。但很遗憾,URL只有一个,而且现在的浏览器并没有智能到可以通过超链接携带Header信息。我们只能通过附加手段达到目的,这个附加手段毫无疑问就是最后一位主角:Ajax。

Step.3 客户端通过Ajax发送不同的Header请求

准确的说我们利用的是XMLHttpRequest对象,来对服务器发送不同的header请求。在W3C的定义中,不仅能够找到GET、POST,XMLHttpRequest支持的header类型一共包括

  • GET
  • POST
  • HEAD
  • PUT
  • DELETE
  • OPTIONS

这些Methods早在1999年就被定义于RFC2616里,到今天终于有了用武之地,真是可喜可贺。

var client = new XMLHttpRequest();
client.open("GET", "test.txt", true);
client.send();

这就是一个最简单的通过XMLHttpRequest发送请求的例子,同理可以将GET替换为其他Method。如果再加上监听状态变化的readystatechange,以及获得反馈的responseXXX,你会发现Ajax原来就是这么一回事。

这里为了使演示更加简单,使用JQuery的Ajax应用,以下是客户端代码:

	$("img").each(function(){
		var src = $(this).attr("src");
		var aim = $(this);
		$.ajax({
			type: "GET",
			url: src,
			dataType : 'json',
			success: function(json){
				var title= "<p>这是一张名为「" + json.title + "」的相片<br />拍摄于:" + json.date + "<br />你可以访问:" + json.full + "来获得这张照片的全图。</p>";
				aim.after(title);
				aim.attr("alt",json.title);
			}
		});
		return false;
	});

这段代码遍历页面的所有图片,然后对这张图片的URL发送Get请求。发送的请求被我们编写的服务器端接收并取得对应的Json数据并返回,最终在客户端显示出来。

至此,这个最简单的图片REST架构便完成了,或许花这么大功夫最终只显示出一张图片来,还称之为构架,实在是小题大作。但最终能剔除所有冗余信息并实现HTML代码的最简化,我自己是玩的不亦乐乎的。

最后附上全部代码下载,也可以在线查看

付录:HTTP-Header最高绝技之翻墙术

其实在国内有很多AV国的网站上不了,并不是GFW的功劳,而网站为了避免拦截正常的访问,也很少会去封IP段。那么究竟为什么很多XX站不能访问呢,在HTTP-Header中,有一个叫Accept-Language的字段负责描述用户的系统语言,国内的Accept-Language值一般都是zh-cn,zh,AV国的很多网站都是通过识别这个值来区别用户。

那么很简单,更改Accept-Language伪装成AV国用户就可以了。

  • Firefox下,地址栏访问about:config,然后搜索intl.accept_languages,将值由zh-cn,zh改为ja即可。
  • IE下,工具——Internet选项——语言——将列表里的语言全部删除即可。

恩恩,这也只是一个技术问题,大家回去自行研究吧。

Read More

[07-23] 基于Picasa、PHP、AJAX的图片REST架构的简单实现(3)

前情提要:基于Picasa、PHP、AJAX的图片REST架构的简单实现(1)
基于Picasa、PHP、AJAX的图片REST架构的简单实现(2)

之前我们从远端获得了图片信息,但是这些和REST还是不沾边的。访问同一个URL,要想获得不同的信息,以目前的软硬件条件,最好的实现方法还是对HTTP Headers进行处理。所以这次的话题是——

Step.2 服务器端接受不同的HTTP Headers返回不同的信息

既然是服务器端,我们仍然采用PHP实现。

PHP对于Header信息的处理是很丰富的,常见的Header都已经存放在预定义变量$_SERVER中了。如果你对什么是Header还没有概念,可以在Firefox中安装一个Live HTTP Headers自行体验一下。

现在问题是:如此之多的Header,到底选择哪个或者哪几个来进行分析?用户的客户端语言,浏览器,IP等等,都是可以进行发挥的。这里为了简单说明问题,选择REQUEST_METHOD,HTTP_REFERER以及HTTP_X_REQUESTED_WITH来进行演示。

简单说明这三个参数:

  • REQUEST_METHOD是页面的请求方法,也是目前REST实现的核心。
  • HTTP_REFERER包含了用户的访问来源,一般是用户前一个访问的URL
  • HTTP_X_REQUESTED_WITH则代表这是一个Xmlhttprequest请求,可以简单的看成是Ajax请求。

以下就是个人的随意发挥了,我所约定的有效服务器反馈包括:

  • 因为不涉及更新等操作,页面的请求方法只限于GET
  • 如果HTTP_REFERER存在,即说明用户在网页中或者通过链接点击访问照片,服务器返回照片的缩略图。
  • 如果HTTP_REFERER不存在,说明用户直接通过URL访问图片,服务器返回照片的全图。
  • 如果HTTP_X_REQUESTED_WITH存在,则说明用户在通过Ajax访问图片,这时返回一个Json格式的照片信息

形象一点用实例说明的话:

点击链接会看到照片的缩略图,将这张照片的地址粘贴到浏览器地址栏直接访问的话,会看到照片的大图。而在Demo中,点击下面的按钮,则可以看到发送Ajax请求到同一个地址时的反馈。

最后还是附上服务器端的代码

require_once 'XML/Unserializer.php';

$Unserializer = &new XML_Unserializer();
$options = array('parseAttributes'   => true);
$Unserializer->setOptions($options);

if($userid && $albumid && $photoid) {
	$xml = "http://picasaweb.google.com/data/feed/api/user/".$_GET['userid']."/albumid/".$_GET['albumid']."/photoid/".$_GET['photoid'];
	$status = $Unserializer->unserialize($xml,true);
	//XML文件解析出错, 报错并退出
	if (PEAR::isError($status)) {
	   die($status->getMessage());
	   exit;
	}
	//如果是一个AJAX访问,返回JSON描述
	elseif($_SERVER['REQUEST_METHOD'] == 'GET' && $_SERVER['HTTP_X_REQUESTED_WITH']){
		$pic = $Unserializer->getUnserializedData();
		$part = explode('.',$pic['media:group']['media:content']['url']);
		$json = json_encode(array(
			'title' => $pic['media:group']['media:description']['_content'] ? $pic['media:group']['media:description']['_content'] : $pic['title']['_content'],
			'date' => gmdate("F d Y H:i:s",strtotime($pic['updated'])),
			'ext' => $part[count($part) -1],
			'full' => $pic['media:group']['media:content']['url']
		));
		echo "($json)";
	}
	//HTTP_REFERER有无的区分
	elseif($_SERVER['REQUEST_METHOD'] == 'GET' && $_SERVER['HTTP_REFERER']) {
		$pic = $Unserializer->getUnserializedData();
		header("Content-Type: image/jpeg");
		curl_exec(curl_init($pic['icon']));
	}
	elseif($_SERVER['REQUEST_METHOD'] == 'GET' && !$_SERVER['HTTP_REFERER']) {
		$pic = $Unserializer->getUnserializedData();
		header("Content-Type: ".$pic['media:group']['media:content']['type']);
		curl_exec(curl_init($pic['media:group']['media:content']['url']));
	}
}
Read More

[07-18] PHP Wiki语法解析类

出于很多考虑,终于还是扔掉了PearText_wiki改用自己写的Wiki语法解析,专用于本Framework。比起Text_wiki来改善,或者说是按自己的习惯改变了很多方面:

  1. 语法上综合了wikipediapuki wiki
  2. 支持html标记插入。
  3. 生成的代码通过W3C Strict验证。
  4. 即使不做解析,也是一篇表意良好,格式工整的text文档,而不像很多乍看上去如天书一般的Wiki语法
  5. 解析速度比Text_wiki快
  6. 加入了很多方便的特殊标记。

目前只是发布前的演示,正式版将附加在Framework中发布,有兴趣的同学可以索取源代码。那么,实验开始:

Title Test

Wiki代码:

=h1=
==h2==
===h3===
====h4====
=====h5=====
======h6======
=======h7=======

转换结果:

h1

h2

h3

h4

h5
h6
=h7=

Table Test

Wiki代码:

! 1 ! 2 ! 3 ! 4 ! 5 !
! 1 | 2 | 3 | 4 | 5 |
! 1  2 !| 3 | 4 | 5 |
! 1  2 || 3 | 4 | 5 |
! 1 | 2  3 || 4 | 5 |
! 1 | 2 | 3  4 || 5 |
! 1 | 2 | 3 | 4  5 ||
! 1  2  3 !!| 4 | 5 |
! 1 | 2  3  4 ||| 5 |
! 1 | 2 | 3  4  5 |||
! 1  2  3  4 !!!| 5 |
! 1 | 2  3  4  5 ||||
! 1  2  3  4  5 |||||

! ---------- ! ----------- ! ---------- !
!left        |        right|   middle   |

转换结果:

1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
---------- ----------- ----------
left right middle

Paragraph Test

Wiki代码:

//Remark will not be parse
This is a normal paragraph.

This is another normal paragraph.

This is a paragraph with newline of br mark.
This is a paragraph with newline of br mark.
This is a paragraph with newline of br mark.

转换结果:

This is a normal paragraph.

This is another normal paragraph.

This is a paragraph with newline of br mark.
This is a paragraph with newline of br mark.
This is a paragraph with newline of br mark.


Blockquote Test

Wiki代码:

> Blockquote Level1
>> Blockquote Level2
>> Blockquote Level2
>>> Blockquote Level3

转换结果:

Blockquote Level1

Blockquote Level2

Blockquote Level2

Blockquote Level3

Blockquote Level3


List Test

Wiki代码:

* ul list level1
** ul list level2
** ul list level2
*** ul list level3
**** ul list level4
**** ul list level4
* ul list level1
** ul list level2
* ul list level1

# ol list level1
## ol list level2
## ol list level2
### ol list level3
#### ol list level4
#### ol list level4
# ol list level1
## ol list level2
# ol list level1

转换结果:

  • ul list level1
    • ul list level2
    • ul list level2
      • ul list level3
        • ul list level4
        • ul list level4
  • ul list level1
    • ul list level2
  • ul list level1
  1. ol list level1
    1. ol list level2
    2. ol list level2
      1. ol list level3
        1. ol list level4
        2. ol list level4
  2. ol list level1
    1. ol list level2
  3. ol list level1

Advance Test

Wiki代码:

Wiki Parser can identify a url [http://allo.ave7.net/] or an image [http://www.ave7.net/logo.gif] with [http://allo.ave7.net/|account].
You can also use <i><b>Html Marks</b></i> inline.
How forcibly specify this is a url [link:http://www.ave7.net/logo.gif] or an image 
[img:http://allo.ave7.net/photo/picasa/allovince/5220926002522558673/5220926248939178194|photo].

转换结果:

Wiki Parser can identify a url http://allo.ave7.net/ or an image http://www.ave7.net/logo.gif with account.
You can also use Html Marks inline.
How forcibly specify this is a url http://www.ave7.net/logo.gif or an image
photo.

Read More

[07-08] Vim配置外一篇(中文化、输入法、代码补全等)

Vim不愧是地球上最强的文本编辑器之一(不加之一恐怕Emacs用户会有意见- -),用Vim就像用Foobar一样,必须先调教一番,使之很好的符合自己的习惯才能达到最高的效率。

之前(前情提要:非中文系统下Gvim中文化解决方法)提到了Vim在其他语言Win32平台下的中文化实现,这里再做一些补充修订:

多语言平台下的中文化实现

首先是编码设置

"设置内核为UTF-8
set enc=utf-8
"设置解码顺序,这个顺序经测试可以很好的识别UTF-8,JIS,GBK
set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936

然后设置界面

"设置内核为UTF-8
set enc=utf-8
"设置解码顺序,这个顺序经测试可以很好的识别UTF-8,JIS,GBK
set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936

注意这里需要下载Vim的中文文档

IME输入法切换设置

在Win32环境下,Vim总是会自作聪明的自动切换到IME输入法。如果想要关闭自动切换,只需要设置

set iminsert=0 imsearch=0

即可,但由于Vim提供了判断IME输入是否打开的multi_byte_ime,我们就可以更加智能的加一些处理

if has('multi_byte_ime')
	"未开启IME时光标背景色
	hi Cursor guifg=bg guibg=Orange gui=NONE
	"开启IME时光标背景色
	hi CursorIM guifg=NONE guibg=Skyblue gui=NONE
	" 关闭Vim的自动切换IME输入法(插入模式和检索模式)
	set iminsert=0 imsearch=0
	" 插入模式输入法状态未被记录时,默认关闭IME
	"inoremap <silent> <ESC> <ESC>:set iminsert=0<CR>
endif

以上设置可以记忆IME开启状态,并用不同的光标颜色提示当前输入法

代码自动补全

实现代码补全需要插件Ctags,将下载的Ctags解压到任意文件夹,然后将Ctags目录追加到环境变量里,之后我们进入项目所在根目录,运行Ctags -R,Ctags会解析所有项目文件并生成一个类似索引的tags文件,然后Vim运行补全时会从tags文件中取得数据。

当然如果更新了类函数定义,也要再次运行Ctags重新生成一次索引,这没有Eclipse那样华丽而且智能,但相比较那些专用IDE的体积和启动速度,Vim的表现仍然非常出色。

默认的代码补全快捷键是Ctrl+X Ctrl+O,可以使用插件SuperTab将快捷键与Tab键合并

自定义快捷键

Normal模式下可以很方便的用nmap设定自定义快捷键,不过可惜的是键盘上的键位也已经被占用的七七八八了。仅列举自己常用的两个作为例子:

nmap mm :%s/\r//g

双击m键可以删除Win下生成的多余换行符CR(在Vim中可以看到蓝色的^M)

nmap tt :%s/^\([\s ]\+\)/    /g<cr>:%s/^更新时间.*\d$//g<cr>:%s/<a href.*<\/a>$//g<cr>:%s/\([\s ]*\n\)\+/\r\r/<cr>

这个就比较复杂一点,双击t键实现对在起点下载的TXT文本进行排版并删除里面多余的广告等。

最终效果截图

Vim of AlloVince

至懒人

好吧,贴出自己的配置,如果只想复制粘贴的同学可以各取所需,不过注意配置对应的插件

set nocompatible
source $VIMRUNTIME/vimrc_example.vim
source $VIMRUNTIME/mswin.vim
behave mswin

"设置工作目录为当前编辑文件的目录
set bsdir=buffer
set autochdir

"编码设置
set enc=utf-8
set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936

"语言设置
set langmenu=zh_CN.UTF-8
language message zh_CN.UTF-8
set guifont=NSimSun:h10
set helplang=cn
source $VIMRUNTIME/delmenu.vim
source $VIMRUNTIME/menu.vim

"禁止生成临时文件
set nobackup

"搜索忽略大小写
set ignorecase 

"搜索逐字符高亮
set incsearch

"行内替换
set gdefault

"始终显示行号
set nu!

"Tab键的宽度
set tabstop=4

"配色方案
colorscheme rainbow_fruit

"输入法设置
if has('multi_byte_ime')
	"未开启IME时光标背景色
	hi Cursor guifg=bg guibg=Orange gui=NONE
	"开启IME时光标背景色
	hi CursorIM guifg=NONE guibg=Skyblue gui=NONE
	" 关闭Vim的自动切换IME输入法(插入模式和检索模式)
	set iminsert=0 imsearch=0
	" 插入模式输入法状态未被记录时,默认关闭IME
	"inoremap <silent> <ESC> <ESC>:set iminsert=0<CR>
endif

"自动缩进
set ai!

"与Windows共享剪贴板
set clipboard+=unnamed

"Ctags的默认索引(需要插件Ctags)
set tags=$VIMRUNTIME/tags
"添加类型检测
filetype plugin indent on
"智能补全
set completeopt=longest,menu


"快捷键调用WinManager(需要插件WinManager)
let g:winManagerWindowLayout='FileExplorer'
nmap ff :WMToggle<cr>
nmap mm :%s/\r//g<cr>
"规范行首空格<cr>去除多余字符<cr>删除空白行<cr>规范行数
nmap tt :%s/^\([\s ]\+\)/    /g<cr>:%s/^更新时间.*\d$//g<cr>:%s/<a href.*<\/a>$//g<cr>:%s/\([\s ]*\n\)\+/\r\r/<cr>

"通过ctrl+方向键切换窗口(需要插件MiniBufExplorer)
let g:miniBufExplMapCTabSwitchBufs = 1
let g:miniBufExplMapWindowNavArrows = 1

至更懒的人

好吧,我放下载就是了…… 点击我试试本Blog新增的下载功能吧,下载后解压到D:根目录,将Ctags目录(D:\Vim\vim71\plugin\ctags)加入环境变量即可

Read More

[07-03] 官方同步插件Weave0.2 for Firefox3试用简评

Weave是Mozilla官方推出的浏览器同步项目,目前Firefox的同步插件Google Browser Sync已经停止了开发,所以Firefox3.0中尚没有可用的同步插件,而Weave0.2的推出给FF3带来了一点希望。

安装,重启,试用……一个小时后我对Weave0.2的表现只有四个字可以形容:“惨不忍睹”。

首先是不友好,账户注册完毕到数据上传是完全没有问题的,但如果要下载同步数据,需要从邮件激活Weave服务,否则会一直提示连接服务器超时。基本的提示信息都起不到相应的向导作用,很难相信这是面向普通用户的产品。

然后是速度,Weave的同步不是像Google Browser Sync那样即时通信,而是退出FF后执行,而服务器又慢到不能忍,每次退出都要停顿30秒至数分钟,最可怕的是如果强行中断同步则会驻留一个 Firefox进程在内存中,真怀疑这不是官方插件,而是官方病毒- -|||

对于真正的同步功能也很难让人满意,用作测试的数据是1000个左右的书签,但同步过程中浏览器却严重拖慢,连正常的浏览都无法进行。不知道是服务器速度影响还是插件本身缺陷。

虽然Weave的野心很大,在预定开发的功能里还能看到插件同步等等让人浮想联翩的词汇,但在一个勉强能用的版本出现之前,需要同步功能的同学还是老老实实用FF2.0+Google Browser Sync吧

另外补充一个Firefox3 css hack之JQuery版

$.browser.mozilla && parseFloat($.browser.version) > 1.8

用js获得的FF3的版本并不是软件开发版本3.0,而是Gecko内核版本1.9,很有意思

Read More

[07-02] Django with mod_python环境搭建总结

Django是经常与Rails相提并论的Python Web框架。但别的姑且不说,Django的环境搭建实在是不够亲切,简单的搭建过程中被雷到多次,特记录如下以供备忘。

安装Django

确保在Django安装之前已经安好了Python。

Django的最新Source可以从SVN获得:http://code.djangoproject.com/svn/django/trunk/

然后执行Django的setup.py

python setup.py install

这里建议把python目录下的script文件夹加入环境变量

安装Apache的mod_python模块

虽然Django内置了Web服务器,但官方建议使用Apache的mod_python模块(- -|||那你还写他干什么)

安装好Apache后,从http://www.modpython.org/获得mod_python并安装(注意下载对应的python和Apache版本)

安装完毕后Apache目录下的modules文件夹内会有mod_python.so,在httpd.conf中写入

LoadModule python_module modules/mod_python.so

将mod_python模块加载进来然后重启Apache

创建Django项目

进入到在Apache的web页面目录下运行

django-admin.py startproject newtest

至此我们的第一个Django项目便成功创建了,此时需要牢记项目名称『newtest』,因为真正的雷才刚刚开始- -。

基于Location的Mod_python访问配置

同样是修改httpd.conf,下面是来自Django官网的配置例子

<Location "/mysite/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    PythonDebug On
    PythonPath "['/path/to/project'] + sys.path"
</Location>

这里有三个参数需要注意:

  1. Location "/mysite/":这个参数是最终在url上反映出来的地址,也就是说目前我们访问Django项目所用的url就是http://localhost/mysite/,此参数可以自由更改,阿猫阿狗都可以。
  2. mysite.settings :这里的mysite必须是Django的项目名,即是刚才所创建的『newtest』,mod_python通过项目名来载入settings.py从而加载整个项目。此处设置不当会出现 ImportError: Could not import settings 'xxx.settings' (Is it on sys.path? Does it have syntax errors?): No module named xxx.settings 错误。
  3. ['/path/to/project'] : 这个参数是最雷的,需要设置为相对于Django项目的父目录,也就是运行django-admin.py startproject时的所在目录。

因此我的Apache的htdocs目录位于D:\xampp\htdocs,最终设置结果为

<Location "/newtest/">
    SetHandler python-program
	PythonPath "sys.path+['D:/xampp/htdocs']"
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE newtest.settings
    PythonDebug On
</Location>

然后重启Apache,访问http://localhost/newtest/,就可以看到亲切的django运行画面了。

Hello Django

终于可以开始第一个程序了,在Django项目下新建一个helloworld.py文件,内容为

from django.http import HttpResponse

def index(request):
	return HttpResponse("Hello, Django.")

然后编辑urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
	(r'^newtest/index', 'newtest.helloworld.index'),
)

最后重启Apache - -|||,注意Django的所有配置更新都是需要重启Apache的……通过http://localhost/newtest/index看看结果吧……

吐槽

总体来说Django的初始配置给我的印象是很不友好的,违反惯性思维的路径设置;每追加一个URL就要重启一次服务简直就是IIS的再现;而舍弃成熟的 Mod_rewrite模块不用,将所有Url统一通过PythonHandler用正则表达式解析后转发,比起强大的mod_rewrite来也未必能提高多少灵活性。或许作者有自己的考量,但作为一个快速开发的框架,Django在易用性上还需要更加琢磨吧。

PS:人生はいいことがあったり、悪いことがあったり、そのたびに喜んだり、悲しんだり、と言いうことだな

Read More

[06-27] 基于Picasa、PHP、AJAX的图片REST架构的简单实现(2)

前情提要:基于Picasa、PHP、AJAX的图片REST架构的简单实现(1)

在前面展示的DEMO中,迫不及待的同学或许已经打开图片链接看过了,但很遗憾,这张图片并不存在于ave7.net的服务器上。我们首先要了解的是标题中的第一个主角Picasa。

来自Google的Picasa无疑是目前互联网最富有代表性的网络相册之一,而我选择Picasa而不是其他风头更劲的Flickr等等的原因有三:

  1. Google的服务很稳定
  2. API有很大发挥的余地
  3. 强劲的客户端支持

Picasa的API文档在这里,有兴趣的同学可以自行慢慢研究,关于本文所涉及的内容,我们只需要知道两点:

  • Picasa的API是以RSS形式发布的
  • 在Picasa中准确定位一张图片需要三个参数:用户名、相册id、相片id

所以在上面的URL中,我们引入这三个参数,经由解析Picasa的API,就可以得到这张图片的所有信息:缩略图、原图、拍摄地点、标签……不一而足。而上述URL,则是我们提到的服务器端的请求分析器,用PHP来实现。

Step.1 服务器端解析Picasa API并显示缩略图

为了更好完成这个目标,这里涉及的知识有

  1. 借助Apache的URL Mod_Rewrite模块来规整URL;
  2. 利用PHP的Curl函数组来获取远端文件;
  3. 用PHP的PEAR库中的XML_Serializer来解析XML文件;

当然本文的重点不是详细讲解以上这些技术,编码上的细节问题会一笔带过,文章的核心始终是框架的搭建。

假设服务器PHP文件名为_loadpic.php,在mod_rewrite模块开启后,同目录下建立一个.htaccess文件,内容为

RewriteEngine On

RewriteRule   ^photo\/picasa\/(\w+)\/(\d+)\/(\d+)    _loadpic.php?userid=$1&albumid=$2&photoid=$3

_loadpic.php文件的内容为

//引入XML_Serializer
require_once 'XML/Unserializer.php';
$Unserializer = &new XML_Unserializer();
$Unserializer->setOptions(array('parseAttributes'   => true));

if($userid && $albumid && $photoid) {
    $xml = "http://picasaweb.google.com/data/feed/api/user/".$_GET['userid']."/albumid/".$_GET['albumid']."/photoid/".$_GET['photoid'];
    $status = $Unserializer->unserialize($xml,true);
    //XML文件解析出错, 报错并退出
    if (PEAR::isError($status)) {
       die($status->getMessage());
       exit;
    }
    $pic = $Unserializer->getUnserializedData();
    header("Content-Type: image/jpeg");
    //Curl获得远端文件,Curl模块需要在PHP.ini的单独开启。
    curl_exec(curl_init($pic['icon']));
    }
}

而通过以上处理,我们达到了初步的目标:通过用户名、相册id、相片id三个参数定位一张照片,访问并解析Picasa API并获得我们需要的图片,然后显示出来。

这里是我们初步实现的结果。

Read More

[06-26] 基于Picasa、PHP、AJAX的图片REST架构的简单实现(1)

HTML总是以链接地址的方式引入图片,尽管我们能在网页内嵌入以BASE64编码后的图片字符,但终究网页不是Word,传输方式决定了一个表意完善,可供用户选择性显示的HTML文本,要好过夹杂了臃肿不堪的媒体文件代码的文档。

但是传统的图片外置方式,带来了很多附加的问题

  1. 服务器地址经常变动,容易过期
  2. 如果采用缩略图,则必然产生一个新的与原图无关的URL,带来大量的冗余
  3. 包含信息量不足,目前图片的所有附加信息(时间,拍摄地点,描述,分类等等)仅仅使用alt属性来对图片进行简单描述,远远不足以应对Web2.0网状的Tag关联描述

好在一切有了REST!

REST构架下的互联网是那样美好,所有的资源都有唯一的,表意良好的资源定位,无需再为页面间无意义的跳转发愁,资源检索的设计空前简单……

但这一切在现有的B/S模式基础上实现的话,代价是极为高昂的。现有的浏览器无法根据用户对单一超链接的点击判断用户的动作究竟是要访问,更新还是删除。同样的,服务器端也只能使用程序本身的入口来分析Header并判断用户究竟要干什么,而不是自动的将不同的Header请求分发到对应接口。

所以一个简单的REST构架实现,在现有的设备中,或者说在我的这个简单实现中,至少需要一个将超链接转换为客户端请求的分析器(AJAX),一个服务器端的请求分析器(PHP),一个将针对各种请求的转发器(PHP+Picasa API)。

而更重要的实现REST构架之前,我们需要做的不仅仅是考虑能不能实现,更需要权衡构架实现所需花销与实现后带来收益是否相符。

那么是否相符呢?还是用最终的结果来说话吧。

点击查看DEMO

Demo中实际的HTML代码只有一行

<img class="photo" src="photo/picasa/allovince/5213571636180988625/5213571644436936978"/>

和普通的图片引入没有任何区别,但最终我们可以在页面上看到这张照片的标题、拍摄时间、原图等等附加信息,当然本Blog也是通过这种方法进一步扩展,搭配了华丽的Lightbox特效等等,有兴趣的同学可以自行翻看。

总之抛去最后的结果不谈,这个REST构架应用的最终结果就是,用户一切所要做的,只是提供上面这样的一行代码,而获得额外的相关信息以及丰富的扩展应用。

Read More

[06-23] 同学们来玩吧

久哈利之窗(Johari Window),貌似有点意思的测试
这是我的测试地址
http://find.veryfind.net/user.asp?user=1334

有兴趣的朋友也可以爬墙到
http://find.veryfind.net/
添加自己的测试

Read More

[06-18] Firefox3插件推荐(Allo的Firefox专贴 part.2)

Firefox3.0正式版在经历的无数的Beta和RC之后终于发布了,比起1.5到2.0的升级来,这次的版本更新显然要受瞩目的多,大多数插件都能及时跟进让升级的花费减少了很多。

之前针对FF2.0写过一篇插件推荐
本次在前文的基础上修修补补,权当放松

浏览器内部改善

浏览器外观改善

浏览器操作改善

浏览内容改善

开发者用

顺便一提,IE下的对应工具也是存在的,当然质量难免要打个折扣- -

离线工具

整体来说FF3.0是很让人满意的,虽然最关键的内存和启动没有明显区别,但细节之处的修改多不胜数,即使一个插件也不装,也足够平易近人了,所以2.0用户无需犹豫,可以立即升级。

Read More
105 - 1/111234...下一页 末页
Now Loading...