首页
关于
联系我
Search
1
小米路由器4A千兆版(R4A) 关闭ipv6 防火墙
90 阅读
2
小米路由器4A千兆版(R4A)开启ssh
85 阅读
3
win11不能访问共享0x800704f8
78 阅读
4
华硕主板vga亮白灯
39 阅读
5
racknerd配置IPV6
36 阅读
未分类
各种资料
我的分析
技术活
游记
真相
笔记
经历
财务知识
资源类
软文
统计学
计划本
事件记录
反思
登录
Search
标签搜索
问题
linux
vps
debian
测试
其他
apt-get
库
wordpress
cdn
code
设置
信息
IP
nginx
应用
推荐
搬家
操作
bae
Typecho
累计撰写
493
篇文章
累计收到
0
条评论
首页
栏目
未分类
各种资料
我的分析
技术活
游记
真相
笔记
经历
财务知识
资源类
软文
统计学
计划本
事件记录
反思
页面
关于
联系我
搜索到
3
篇与
的结果
2015-07-28
PHP 5.0~5.6 各版本兼容性的 cURL 文件上传
最近在搞一个针对sm.ms 图片站的上传插件,然后就遭遇curl 坑,也不知道是年龄大了,还是PHP 真的越来越麻烦了。转载一篇文章,作为备注吧最近做的一个需求,要通过PHP调用cURL,以multipart/form-data格式上传文件。踩坑若干,够一篇文章了。重要警告没事不要读PHP的官方中文文档!版本跟不上坑死你!不同版本PHP之间cURL的区别PHP的cURL支持通过给CURL_POSTFIELDS传递关联数组(而不是字符串)来生成multipart/form-data的POST请求。传统上,PHP的cURL支持通过在数组数据中,使用“@+文件全路径”的语法附加文件,供cURL读取上传。这与命令行直接调用cURL程序的语法是一致的:curl_setopt(ch, CURLOPT_POSTFIELDS, array( 'file' => '@'.realpath('image.png'), )); equals $ curl -F "file=@/absolute/path/to/image.png" <url> 但PHP从5.5开始引入了新的CURLFile类用来指向文件。CURLFile类也可以详细定义MIME类型、文件名等可能出现在multipart/form-data数据中的附加信息。PHP推荐使用CURLFile替代旧的@语法:curl_setopt(ch, CURLOPT_POSTFIELDS, [ 'file' => new CURLFile(realpath('image.png')), ]); PHP 5.5另外引入了CURL_SAFE_UPLOAD选项,可以强制PHP的cURL模块拒绝旧的@语法,仅接受CURLFile式的文件。5.5的默认值为false,5.6的默认值为true。但是坑的一点在于:@语法在5.5就已经被打了deprecated,在5.6中就直接被删除了(会产生 ErorException: The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead)。对于PHP 5.6+而言,手动设置CURL_SAFE_UPLOAD为false是毫无意义的。根本不是字面意义理解的“设置成false,就能开启旧的unsafe的方式”——旧的方式已经作为废弃语法彻底不存在了。PHP 5.6+ == CURLFile only,不要有任何的幻想。我的部署环境是5.4(仅@语法),但开发环境是5.6(仅CURLFile)。都没有压在5.5这个两者都支持过渡版本上,结果就是必须写出带有环境判断的两套代码。现在问题来了……(挖掘机滚远点!)环境判断:小心魔法数字!我见过这种环境判断的代码:if (version_compare(phpversion(), '5.4.0') >= 0) 我对这种代码的评价只有一个字:屎。这个判断掉入了典型的魔法数字陷阱。版本号莫名其妙的出现在代码之中,不查半天PHP手册和更新历史,很难明白作者被卡在了哪个功能的变更上。代码应该回归本源。我们的实际需求其实是:有CURLFile就优先采用,没有再退化到传统@语法。那么代码就来了:if (class_exists('\CURLFile')) { $field = array('fieldname' => new \CURLFile(realpath($filepath))); } else { $field = array('fieldname' => '@' . realpath($filepath)); } 建议明确指定的退化选项从可靠的角度,推荐指定CURL_SAFE_UPLOAD的值,明确告知php是容忍还是禁止旧的@语法。注意在低版本PHP中CURLOPT_SAFE_UPLOAD常量本身可能不存在,需要判断:if (class_exists('\CURLFile')) { curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true); } else { if (defined('CURLOPT_SAFE_UPLOAD')) { curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false); } } cURL选项设置的顺序不管是curl_setopt()单发还是curl_setopt_array()批量,cURL的选项总是设置一个生效一个,而设置好的选项立刻就会影响cURL在设置后续选项时的行为。例如CURLOPT_SAFE_UPLOAD就和CURLOPT_POSTFIELDS的行为有关。如果先设置CURLOPT_POSTFIELDS再设置CURLOPT_SAFE_UPLOAD,那么后者的约束作用就不会生效。因为设置前者时cURL就已经把数据实际的识读处理完毕了!cURL有那么几个选项存在这种坑,务必小心。还好这种存在“依赖关系”的选项不多,机制也不复杂,简单处理即可。我的方法是先批量设置所有的选项,然后直到curl_exec()的前一刻才用curl_setopt()单发设置CURLOPT_POSTFIELDS。实际上在curl_setopt_array()用的数组中,保证CURLOPT_POSTFIELDS的位置在后边也是可靠的。PHP的关联数组是有顺序保障的,我们也可以假设curl_setopt_array()内部的执行顺序一定是从头到尾按顺序[注A],所以尽可放心。我的做法只是在代码表现上加个多余的保险,突出强调顺序的重要性防以后手贱。命名空间PHP 5.2或以下的版本没有命名空间。代码中用到了空间分隔符\就会引发解析器错误。要照顾PHP 5.2其实容易想,放弃命名空间即可。要注意的反倒是有命名空间的PHP 5.3+。无论是调用CURLFile还是用class_exists()判断CURLFile的存在性,都推荐写成\CURLFile明确指定顶层空间,防止代码包裹在命名空间内的时候崩掉。
2015年07月28日
2 阅读
0 评论
0 点赞
2015-06-02
新版Conoha利用API上传镜像安装系统
感谢hostloc “dzxx36gyy” 做出的贡献经过一番折腾,楼主我已经搞定了新版Conoha利用API上传ISO安装系统的方法了,当然, 大部分人还是会拿来安装windows(水晶党退散,迅雷这么坑还玩?)。 本教程主要利用如下API: 1.ISO上传API https://www.conoha.jp/docs/compute-iso-download-add.html 2.查看已上传的ISO的API https://www.conoha.jp/docs/compute-iso-list-show.html 3.挂载已上传的ISO的API https://www.conoha.jp/docs/compute-insert_iso_image.html 4.卸载ISO的API https://www.conoha.jp/docs/compute-eject_iso_image.html 5.身份验证API https://www.conoha.jp/docs/identity-post_tokens.html 6.VPS详细信息查看API https://www.conoha.jp/docs/compute-get_vms_detail_specified.html 首先,参照官方文档,我发现大部分操作并没有利用到Conoha面板API中的密码,而是用到了 X-Auth-Token,然后我找啊找,发现身份验证的API里面有一项可以生成这个。命令如下: curl -i -X POST \ -H "Accept: application/json" \ -d '{ "auth": { "passwordCredentials": { "username": "API用户名(店铺名称)", "password": "API用户密码(请自己在面板里添加)" }, "tenantId": "店铺ID" } }' \ https://identity.tyo1.conoha.io/v2.0/tokens 这是东京的API,其它地区的自己按照地址格式改。 运行之后会返回一串数据,请注意 { "access": { "token": { "issued_at": "2015-05-19T07:08:21.927295", "expires": "2015-05-20T07:08:21Z", "id": "sample00d88246078f2bexample788f7", 其余省略 这段中的id即为X-Auth-Token,上面那个expires是有效期,之后的操作均要用到X-Auth-Token。 现在我们可以开始上传ISO了,注意,由于官方API系统没建设完全,对http链接支持不完善,请 使用ftp格式的ISO地址(ISO必须带virtio驱动),上传命令如下: curl -i -X POST \ -H 'Content-Type: application/json' \ -H "Accept: application/json" \ -H "X-Auth-Token: (前面有个空格)这里是啥不用我说了吧" \ -d '{ "iso-image": { "url": "ftp格式的ISO地址" } }' \ https://compute.tyo1.conoha.io/v2/店铺ID/iso-images 同样,这个是东京的API地址,其它地区的 请按照格式自己修改 命令运行之后会返回数据,是ISO地址和你的API信息 之后我们应该查看ISO是否成功上传,命令如下 curl -i -X GET \ -H 'Content-Type: application/json' \ -H "Accept: application/json" \ -H "X-Auth-Token: (同样前面有个空格)" \ https://compute.tyo1.conoha.io/v2/店铺ID/iso-images 返回数据大概是这样的 { "iso-images": [ { "url": "ftp://ftp.riken.jp/Linux/centos/6.6/isos/x86_64/CentOS-6.6-x86_64-minimal.iso", "path": "/mnt/isos/repos/tenant_iso_data/43b36734a9e541fd91a62fc63ee93fed/CentOS-6.6-x86_64-minimal.iso", "ctime": "Fri Oct 24 23:22:57 2014", "name": "CentOS-6.6-x86_64-minimal.iso", "size": 401604608 }, { "url": "http://ftp.riken.jp/Linux/centos/7/isos/x86_64/CentOS-7.0-1406-x86_64-Everything.iso", "path": "/mnt/isos/repos/tenant_iso_data/43b36734a9e541fd91a62fc63ee93fed/CentOS-7.0-1406-x86_64-Everything.iso", "ctime": "Sat Jul 5 07:16:46 2014", "name": "CentOS-7.0-1406-x86_64-Everything.iso", "size": 7062159360 } ] } 出现在里面的代表成功上传了,挂载镜像会使用到path 挂载命令如下(前提条件:先创建vps,然后关机,在面板——服务器——VPS(别真以为有个选项叫vps啊)——vps设置——控制台键盘映射改为en-us curl -i -X POST \ -H "Accept: application/json" \ -H "X-Auth-Token: 不说了" \ -d '{"mountImage": "前面查看已上传的ISO里的path"}' \ https://compute.tyo1.conoha.io/v2/店铺ID/servers/VPS的UUID(点开vps管理,在VPS设置里和网址上有)/action 接下来要查看VPS详细信息,确认是否成功挂载 curl -i -X GET \ -H "Accept: application/json" \ -H "X-Auth-Token: 不说了" \ https://compute.tyo1.conoha.io/v2/店铺ID/servers/上一步里的UUID 返回信息里自己看吧,有你ISO的path就代表挂载成功了。 然后你开机吧(之前挂载步骤必须在关机状态下进行,不然会失败) 开启VNC,重启,会提示你按任意键以从光驱启动,之后不用我说了吧,唯一需要注意的一点就是 VPS设置里的那个控制台键盘映射必须换成en-us(电脑是日语键盘的请无视),不然各种灵异事件。 对了,安装完之后请卸载ISO,当然你不卸貌似也没问题,请在关机状态下运行 curl -i -X POST \ -H "Accept: application/json" \ -H "X-Auth-Token: 不说了" \ -d '{"unmountImage": ""}' \ https://compute.tyo1.conoha.io/v2/店铺ID/servers/VPS的UUID/action 返回信息没啥东西,无视吧。 好了,本教程END (别问我这些命令在什么里面运行……,随便找台联网的linux机子都行)
2015年06月02日
9 阅读
0 评论
0 点赞
2012-07-08
纠结的淘宝api签名
因为网站想添加个功能,就是自动转换淘宝客链接,尝试弄了下淘宝api,签名部分折腾的头疼,一直被淘宝的api测试工具误导,一直被网上乱七八糟的说法误导。做下记录,别忘记了。签名规则是:官方说明:http://open.taobao.com/doc/detail.htm?id=111#s6除了图片和签名,其余提交的所有参数都要md5下。参数要按照升序(a-z)排列。如果参数首字母相同,就按照第二个字母排序。总结下sign = 大写(md5(appsecret+appkey+参数+appsecret))另外拼装url的时候要注意,参数值都要url编码的。解释的好苍白,还是上代码吧。没有appkey 自己添加,因为是测试代码,比较乱,自己修改$sign = ''; $appsecret = ""; $appkey = ""; $ctime = date("Y-m-d H:i:s"); $timestamp = urlencode($ctime); $parame = array( 'app_key'=>$appkey, 'fields'=>'num_iid,title,nick,pic_url,price', 'format'=>'xml', 'method'=>'taobao.taobaoke.items.convert', 'nick'=>'', 'num_iids'=>'15293327612', 'sign_method'=>'md5', 'timestamp'=>'', 'v'=>'2.0', ); $parame['timestamp']=$ctime; ksort($parame); foreach($parame as $key => $value){ $sign .= $key.$value; } $sign = $appsecret.$sign.$appsecret; //echo $sign; $sign = strtoupper(md5($sign)); $apiurl = "http://gw.api.taobao.com/router/rest?sign=".$sign."&"; foreach($parame as $key => $value){ $apiurl .= $key.'='.urlencode($value).'&'; } echo $apiurl;
2012年07月08日
11 阅读
0 评论
0 点赞