Submitted by gouki on 2015, June 19, 9:13 AM
众所周知,用curl上传只要设置4个变量即可(非HTTPS网站),那就是curlopt_url,curlopt_post,curlopt_returntransfer,curlopt_postfields,当然这4个都是大写。
curlopt_post,curlopt_returntransfer 都是 true,curlopt_url则是你要提交的网址,那么剩下的,curlopt_postfields就是你要上传的内容了。
上传文件在这里也变得非常简单,只需对应的值前面加个“@”即可,如curl_setopt($ch,CURLOPT_POSTFIELDS,array('file'=>'@/var/www/images/abc.jpg')); 文件通过realpath判断后存在的即可。
但是,这一切在php5.6里就发生了改成。php5.6不再支持@这样的上传方式,只能使用curl_file_create的方式来,所以上面的代码要改成
PHP代码
- curl_setopt($ch,CURLOPT_POSTFIELDS,array('file'=>curl_file_create('/var/www/images/abc.jpg','image/jpg','abc')));
看看文档里怎么说:
XML/HTML代码
- CURLFile should be used to upload a file with CURLOPT_POSTFIELDS.
然后官网的手册中的最后一条评论,仿佛是看不下去,写了个处理上传的程序
PHP代码
- There are "@" issue on multipart POST requests.
-
- Solution for PHP 5.5 or later:
- - Enable CURLOPT_SAFE_UPLOAD.
- - Use CURLFile instead of "@".
-
- Solution for PHP 5.4 or earlier:
- - Build up multipart content body by youself.
- - Change "Content-Type" header by yourself.
-
- The following snippet will help you :D
-
- <?php
-
-
-
-
-
-
-
-
-
- function curl_custom_postfields($ch, array $assoc = array(), array $files = array()) {
-
-
- static $disallow = array("\0", "\"", "\r", "\n");
-
-
- foreach ($assoc as $k => $v) {
- $k = str_replace($disallow, "_", $k);
- $body[] = implode("\r\n", array(
- "Content-Disposition: form-data; name=\"{$k}\"",
- "",
- filter_var($v),
- ));
- }
-
-
- foreach ($files as $k => $v) {
- switch (true) {
- case false === $v = realpath(filter_var($v)):
- case !is_file($v):
- case !is_readable($v):
- continue;
- }
- $data = file_get_contents($v);
- $v = call_user_func("end", explode(DIRECTORY_SEPARATOR, $v));
- $k = str_replace($disallow, "_", $k);
- $v = str_replace($disallow, "_", $v);
- $body[] = implode("\r\n", array(
- "Content-Disposition: form-data; name=\"{$k}\"; filename=\"{$v}\"",
- "Content-Type: application/octet-stream",
- "",
- $data,
- ));
- }
-
-
- do {
- $boundary = "---------------------" . md5(mt_rand() . microtime());
- } while (preg_grep("/{$boundary}/", $body));
-
-
- array_walk($body, function (&$part) use ($boundary) {
- $part = "--{$boundary}\r\n{$part}";
- });
-
-
- $body[] = "--{$boundary}--";
- $body[] = "";
-
-
- return @curl_setopt_array($ch, array(
- CURLOPT_POST => true,
- CURLOPT_POSTFIELDS => implode("\r\n", $body),
- CURLOPT_HTTPHEADER => array(
- "Expect: 100-continue",
- "Content-Type: multipart/form-data; boundary={$boundary}",
- ),
- ));
- }
好吧,其实多文件上传用这样的方式就挺好。
PHP | 评论:1
| 阅读:22370
Submitted by gouki on 2014, December 14, 10:46 PM
1、 如何获取字符串的长度:
在判断长度是否大于0的时候,if [xxx length ] > 0 就行了。而如果直接用swift,就不能写 if xxx.length > 0 了。因为xxx没有length这个方法。
有两个办法:
- if countElements(xxx) > 0
- if xxx.utf16count > 0
2、swift的delegate不象oc那样一个个的标注,只要在class头上写明就OK了
比如 class ViewController : UIViewController , UIActionSheetDelegate {
}
就能直接用UIActionSheetDelegate中的方法了。然后他们的delegate写self即可
刚开始学。不知道对错,目前就这样先纯做笔记,当然 你也可以delegate: nil 这样代表你这个控件 就不再接受委托了
Tags: swift
Flutter | 评论:0
| 阅读:13589
Submitted by gouki on 2012, May 16, 9:32 AM
老婆用的是palm手机,最近因为摔了(?好象是),导致打电话的时候听不到声音,但是用耳线可以,因为它的电话比较多,所以就帮她买了个iphone4s,之所以买这款手机而不是买android或者wp之类的,是因为,这款手机相对比较简单,比如装软件,删软件。不象安卓还得进入软件管理器里才能进行删除。太麻烦了。
新机入手,第一件事就是剪卡,随手一剪,插入后提示无SIM卡。再到网上查了一下,原来剪卡不是说把芯片剪出来就完事了,主要是要对准中心线,于是对着图片,直接下手一刀,把SIM卡的铜片剪掉一点,再次插入,正常了。哈哈。哥还是很厉害的
然后就是导入通讯录了。不得不说,虽然palm没落了,但是它的一些设计理念还不错的,比如它就支持google通讯录,于是这次换成iphone后,通讯录就不是难事了。
原来我以为在邮件里直接绑定gmail就OK了,但事实告诉我,这是不行的。嗯,网上都说了,还是用exchange吧
于是在exchange里输入了gmail的帐号,点击下一步,会让我输入服务器,这时候输入:m.google.com,再下一步就OK了。
黑黑,通讯录就这么导回来了。轻轻松松啊。
Tags: iphone, google, contacts, palm
Flutter | 评论:0
| 阅读:18704
Submitted by gouki on 2012, April 17, 9:26 AM
来源:http://hi.baidu.com/tangly888/blog/item/62948520121870559358074f.html
翻译苹果文档 地址: 翻译:tangly
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW9
推送通知消息负载内容
每个推送通知都带有内容负载,这个负载内容会被应用程序下载并提醒用户收到数据。负载内容最大允许为256个字节,苹果推送通知服务器拒绝任何超过最大负载字节的推送通知。记住,通知的提交是“尽力而为”,它并不能得到保证。
对于每一个通知,供应商组成一个JSON自动对象来严格遵守RFC 4627协议,这个字典必须通过aps键来包含另一个字典的标示,aps键包含一个或多个属性,指定以下操作:
1. 向用户显示一个提示消息
2. 应用程序图标上的一个徽章号码
3. 可播放的声音
警告: 警告你可以将提示消息,徽章图标号码,播放声音结合成一个单一的通知消息,你应该考虑到推送通知的人机界面问题,例如,用户可能受到频繁的提示消息和警告声音,这然人烦。
当通知到达时,如果这时候目标程序没有运行,这提示消息,声音,徽章号码会被播放或被显示;如果应用程序正在运行,ios将它作为一个NSDictionary对象提供给应用程序委托,这个字典收录了相应COcoa属性列表中的对象
供应商可以指定评估命名以外的消息内容,自定义消息负载内容,自定义值必须使用Json结构和基本类型:字典(对象),数组,字符串,数字,boolean。作为定制消息数据,你不应该包含用户的一些信息。相反,为设置上下文(用户界面)或内部指标为目的来使用它。例如,当供应商发送通知的时候,一个自定义通知消息可能会成为一个会话标示符被消息客户端应用或时间戳确认来使用。提示消息的任何行为都不应该具有破坏性,如删除客户设备上的数据
关键:由于传送不能够被保证,所以你不应该依赖远程通知设施提供有效负载消息内容给应用程序,不要再消息负载内容中带有敏感数据,你使用它仅是告诉用户此应用有新的数据可用了
表3-1中列出了有关苹果服务器消息负载内容的键和预期值
Key
|
类型
|
Comment
|
alert
|
字符串或字典
|
如果包含这个这个属性 iOS 将会显示一个标准的提示. 你可用指定一个字符串作为提醒或作为字典的值. 如果你指定了一个字符串, 它会变成有两个按钮的警报消息: 关闭和显示. 如果用户点击查看, 应用程序将会启动
另外, 你可以指定一个字典来作为提示的内容. 对于这类字典,请查看表3-2
|
badge
|
数字
|
这个数字将作为应用程序的的徽章图标显示. 如果此属性不存在, 任何当前显示的徽章号码将会被删除
|
sound
|
字符串
|
它是捆绑再应用程序的声音文件名. 这个声音文件播放声音警报. 如果这个声音文件不存在或指定默认值,这时会播放预设的警报音. 它的音频必须是兼容的系统数据格式之一; 详细信息,请阅读“”准备定义提示音
|
表3-1 alert属性的子属性
Key
|
Value type
|
Comment
|
body
|
string
|
The text of the alert message.
|
action-loc-key
|
字符串或空
|
如果字符串是指定的, 将显示带有两个按钮的警报, 其行为请看表3-1. 然而, ios 用字符串作为键来获得当前本地化的字符串,并将其用于右边按钮的标题,代替了“view”. 如果字符串值为null,系统将显示一个简单的“确定”按钮,当点击时,将会简单的消除按钮. 看 “Localized Formatted Strings” 获得更多消息
|
loc-key
|
字符串
|
本地提示消息的一个字符串钥匙, 字符串钥匙可以格式化这样%@ and %n$ 在loc-args指定参数变量. 看 “Localized Formatted Strings” 可以获得更多信息.
|
loc-args
|
字符串数组
|
变量的字符串值格式化再loc-key出现. 看 “Localized Formatted Strings” 可以获得更多信息 .
|
launch-image
|
字符串
|
图形文件名在应用程序中已经绑定; 它可能包括扩展或省略. 当用户点击动作按钮或移动动作滑块,图片将会被显示出来. I如果这个属性没有指定, 系统会使用以前的图片,通过在应用程序的Info.plist键来使用图像识别, 或返回到默认的png文件
这个属性再ios4.0才被添加的
|
注意:如果你想要iphone,ipad,ipod touch设备将一个通知作为消息文本来显示,那就的有关闭和显示两个按钮
Tags: 推送, budge, json
Flutter | 评论:0
| 阅读:19748
Submitted by gouki on 2012, March 11, 11:07 AM
该死的command+左箭头。。。写了十分钟的东西全没了。
-------重新开始-----
由于目前的一个项目涉及到的数据库需要跨库跨表操作,而且该库会被频繁的插入、更新、删除,所以相对速度会较慢。但查询量又较大,在一台服务器的情况下,怎么办?分端口主从吧,意义不大,因为某些操作会导致CPU瞬间100%。
这时候我想到了key/value的数据库,想用它来做中间处理,比如大量的内容先经过它,再真正入库,毕竟我不需要过分实时,也不涉及到金钱交易。于是乎就在redis和mongo中间犹豫了。
在这期间咨询了三个人:老王(基于博客http://huoding.com/2012/02/29/146,基于Redis消息系统实现);11爷(redis有pub/sub功能);烂桔(mongo不太适用于单机,redis有内存模式)
基于上述原因,于是选择了redis,那么就开始我的Redis之旅吧
1、安装 Redis ,参考:http://library.linode.com/databases/redis/ubuntu-10.10-maverick(如果我没记错,这应该是11爷推荐的地址,他本来推荐的是Centos下的,但我用的是ubuntu,所以就参考这个了)
先来三个常规操作
XML/HTML代码
- apt-get update
- apt-get upgrade
- apt-get install build-essential
完事之后,接着:
XML/HTML代码
- cd /opt/
- mkdir /opt/redis
- wget http://redis.googlecode.com/files/redis-2.4.8.tar.gz
- tar -zxvf /opt/redis-2.4.8.tar.gz
- cd /opt/redis-2.4.8/
- make
make完后做如下操作,将一些配置文件拷贝到/opt/redis目录下:
XML/HTML代码
- cp /opt/redis-2.4.8/redis.conf /opt/redis/redis.conf.default
- cp /opt/redis-2.4.8/src/redis-benchmark /opt/redis/
- cp /opt/redis-2.4.8/src/redis-cli /opt/redis/
- cp /opt/redis-2.4.8/src/redis-server /opt/redis/
- cp /opt/redis-2.4.8/src/redis-check-aof /opt/redis/
- cp /opt/redis-2.4.8/src/redis-check-dump /opt/redis/
- cp /opt/redis/redis.conf.default /opt/redis/redis.conf
接着,更新/opt/redis/redis.conf:
XML/HTML代码
- daemonize yes
- pidfile /var/run/redis.pid
- logfile /var/log/redis.log
-
- port 6379
- bind 127.0.0.1
- timeout 300
-
- loglevel notice
-
- ## Default configuration options
- databases 16
-
- save 900 1
- save 300 10
- save 60 10000
-
- rdbcompression yes
- dbfilename dump.rdb
-
- dir /opt/redis/
- appendonly no
以上是linode里的配置,你可以参考一下做处理。大部分都一样,但timeout/loglevel/dir这三个参数不太一样。可以看着注释改一下。 linode 中有一个:glueoutputbuf yes ,这个在2.4.8下面会出错,所以我就没有启用它。
接着是加入启用脚本,既然linode有配置参考,那么它就有启动脚本,默认redis是没有给你这些启动脚本的,所以偷懒一下吧,下载linode的脚本:
XML/HTML代码
- cd /opt/
- wget -O init-deb.sh http://library.linode.com/assets/630-redis-init-deb.sh
- adduser --system --no-create-home --disabled-login --disabled-password --group redis
- mv /opt/init-deb.sh /etc/init.d/redis
- chmod +x /etc/init.d/redis
- chown -R redis:redis /opt/redis
- touch /var/log/redis.log
- chown redis:redis /var/log/redis.log
- update-rc.d -f redis defaults
在这一步之后,你就可以直接用/etc/init.d/redis 来 start和stop redis服务了。
2、安装phpredis(https://github.com/nicolasff/phpredis)
在安装之前,先看readme:https://github.com/nicolasff/phpredis/blob/master/README.markdown
看完readme之后你会发现,原来一切是这样的简单啊
OK,先wget 回源代码,然后tar解开目录。。
接着3步搞定:
XML/HTML代码
- phpize
- ./configure
- make && make install
速度超快,make install后,会告诉你redis.so生成在哪里,你将这extension=redis.so,加入到你的php.ini中即可。
3、下载YiiRedis项目。(由于我是用Yii的,所以直接用这个插件了,否则,还是参考一下phpredis的一些用法)
同样,在这里有readme:https://github.com/phpnode/YiiRedis/blob/master/README.md
项目地址:https://github.com/phpnode/YiiRedis(请自行下载)
使用方法也很简单,和db一样,在components下加一个组件:
XML/HTML代码
- "components" => array(
- "redis" => array(
- "class" => "packages.redis.ARedisConnection",
- "hostname" => "localhost",
- "port" => 6379
- ),
- //...
- ),
加完它之后就可以写上一段测试代码了:
PHP代码
- Yii::import("ext.yiiredis.*");
- $list = new ARedisList("aNameForYourListGoesHere");
- $list->add("cats");
- $list->add("dogs");
- $list->add("goods");
- foreach($list as $i => $val) {
- print_r($val) ;
- echo "<br />";
- }
- $list->clear();
直接输出在浏览器中。是不是很HIGH?
------
OK,就介绍到这里,请试用吧。
=------
备注:
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); // don't serialize data
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); // use built-in serialize/unserialize
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY); // use igBinary serialize/unserialize
$redis->setOption(Redis::OPT_PREFIX, 'myAppName:'); // use custom prefix on all keys
由于redis默认不做序列化,因此如果要存储PHP的数据,如:数组、对象,那就必须用第二个setOption进行设置,以便 让数据自动序列化
Tags: redis, yiiredis, phpredis
PHP | 评论:2
| 阅读:45887