一、问题

将图片在windows下用图片查看器修改后,上传到s3中,调用getimagesize获取图片信息总是返回false,其它图片正常;

代码如下:

$fileName = 's3://sdk1/20150317/174290_1_1428371.JPG';
$size = getimagesize($fileName);
var_dump($size);

以上代码总是输出false。

即部分图片调用成功,部分调用失败;

图片上传后,可以对上传的临时文件调用getimagesize获取图片信息;

PHP的版本为5.6.2

二、分析过程:

1、准备知识

先说下PHP中对流的封装,通过函数stream_wrapper_register,我们可以注册一个新的URL,像上面的s3开头的文件;

AWS封装了一套对这类文件的操作,包括读、写、定位、打开目录等函数,这方面资料可以看下PHP文档,AWS的封装代码可以看下AWS的PHP的SDK。

通过追代码,发现对S3文件的请求最终会转成一个HTTPS的请求,https://sdk1.s3.cn-north-1.amazonaws.com.cn/20150317/174290_1_1428371.JPG

2、代码追踪

看下getimagesize函数的实现,

这个是调用php_getimagesize_from_any来实现的,

重要函数为php_getimagesize_from_stream,看下这个函数:

会先读取文件的前三字节,获取文件类型,具体可以看下php_getimagetype函数;

如果是jpg类型的图片,会调用php_handle_jpeg函数,

其中函数php_next_marker会读取文件的二进制流当前字节,根据不同字节作不同的处理,

如果当前字节为宏M_APP0至M_APP15,即0xe0到0xef,表示是APP或变量;

出问题的图片当前是variable,看下php_skip_variables函数

如果当前是一个变量,则要跳过这个变量,读取下一块信息,这里调用php_stream_seek来进行seek操作,

看两块关键代码,上面一段表示seek的位置在已经读取的范围内;

下一块表示这个流不支持seek操作,返回失败;

在我们的例子里,上面表示正常情况,下面表示失败情况的;

我们再回到s3的seek操作的封装:

return $this->cache[self::SEEKABLE] ? fseek($this->stream, $offset, $whence) === 0 : false;

即不支持seek,所以失败了;

明白了吗,原理就是getimagesize为从文件的二进制流中读取图片信息,而这个信息是文件的位置是不固定的,必须一块一块的解析,正常的图片的相关信息是在文件前8192个字节之内,而

出错的是8192之外的,如果在8192之外的,需要先将文件流定位到相应位置,再从该位置读取信息,而s3开头的路径不支持seek操作,导致PHP读不文件元信息。

三、改进方法

改写Stream::seek方法

public function seek($offset, $whence = SEEK_SET)

{

if ($whence == SEEK_SET)

{

$pos = $this->ftell();

if ($pos < $offset)

{

$this->read($offset - $pos);

}

}

return $this->cache[self::SEEKABLE] ? fseek($this->stream, $offset, $whence) === 0 : false;

文件存到aws的S3后, 调用getimagesize失败分析的更多相关文章

  1. 上传文件到aws的s3存储

    只要有aws-cli客户端就可以上传文件到aws的S3存储.可以在任意机器上.这里以centos为例. 1.安装python.pip. # yum install -y python python-p ...

  2. AWS系列-S3实现文件服务页面展示

    最近由于业务需求,对于备份的数据存放到S3上面,并需要页面展示.而且还能下载. 把这个桶里面的对象,都在某个静态页面展示.并且 我可以把这个对象下载下来. 首页内容就是 桶里面的对象. 并且可以随时查 ...

  3. bootstrap的datepicker在选择日期后调用某个方法

    bootstrap的datepicker在选择日期后调用某个方法 2016-11-08 15:14 1311人阅读 评论(0) 收藏 举报 首先感谢网易LOFTER博主Ivy的博客,我才顿悟了问题所在 ...

  4. python调用另一个文件中的代码,pycharm环境下:同文件夹下文件(.py)之间的调用,出现红线问题

    如何调用另一个python文件中的代码无论我们选择用何种语言进行程序设计时,都不可能只有一个文件(除了“hello world”),通常情况下,我们都需要在一个文件中调用另外一个文件的函数呀数据等等, ...

  5. 痞子衡嵌入式:JLink Script文件基础及其在IAR下调用方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是JLink Script文件基础及其在IAR下调用方法. JLink可以说是MCU开发者最熟悉的调试工具了,相比于其他调试器(比如DAP ...

  6. 为什么需要在TypedArray后调用recycle

    当我们没有在使用TypedArray后调用recycle,编译器会提示“This TypedArray should be recycled after use with #recycle()”. 官 ...

  7. shell 脚本文件Windows传到Linux后编码问题

    shell 脚本文件Windows传到Linux后编码问题 下面这个标红的位置出现,是由于脚本从Windows机器上直接传到linux文件格式不对导致的. cat -v a.sh help^M exi ...

  8. java笔试题: ——将e:/source文件夹下的文件打个zip包后拷贝到f:/文件夹下面

    将e:/source文件夹下的文件打个zip包后拷贝到f:/文件夹下面 import java.io.*; import java.util.zip.ZipEntry; import java.uti ...

  9. Java基础知识强化之IO流笔记52:IO流练习之 把一个文件中的字符串排序后再写入另一个文件案例

    1. 把一个文件中的字符串排序后再写入另一个文件 已知s.txt文件中有这样的一个字符串:"hcexfgijkamdnoqrzstuvwybpl" 请编写程序读取数据内容,把数据排 ...

随机推荐

  1. put数据到topic

    基于python3.6 # -*-coding:utf-8 *- __author__ = 'lc_yy' from pykafka import KafkaClient import logging ...

  2. 用WEB方式开发WPF桌面程序

    因为疫情影响,公司裁员,结束了一年多的web开发经历,重新开始做桌面,新公司用的是WPF(居然用的是winform style...),当然这跟本文没有关系...上篇博客写的用后台api和前台浏览器控 ...

  3. PythonCrashCourse 第九章习题

    创建一个名为Restaurant 的类,其方法__init__() 设置两个属性: restaurant_name 和cuisine_type 创建一个名为describe _restaurant ( ...

  4. Web安全攻防(简)学习笔记

    Web安全攻防-学习笔记 本文属于一种总结性的学习笔记,内容许多都早先发布独立的文章,可以通过分类标签进行查看 信息收集 信息收集是渗透测试全过程的第一步,针对渗透目标进行最大程度的信息收集,遵随&q ...

  5. golang 创建 tun 设备

    源码: package main import ( "flag" "fmt" "github.com/pkg/errors" "n ...

  6. 《Head First 设计模式》:模板方法模式

    正文 一.定义 模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 要点: 模板方法定义了一个算法的步骤,每 ...

  7. 封装Vue Element的dialog弹窗组件

    我本没有想着说要封装一个弹窗组件,但有同行的朋友在问我,而且弹窗组件也确实在项目开发中用的比较多.思前想后,又本着样式统一且修改起来方便的原则,还是再为大家分享一个我所封装的弹窗组件吧. 其实,并不是 ...

  8. [U3D + GAD]Egametang开源服务器框架资源管理系统

    Egametang开源服务器框架资源管理系统详解 http://m.gad.qq.com/article/detail/36409 ET GitHub https://github.com/egame ...

  9. 这应该是最适合国内用户的K3s HA方案

    前 言 在面向生产环境的实践中,高可用是我们无法避免的问题,K3s本身也历经多个版本的迭代,HA方案也进行了不断优化,形成了目前的比较稳定的HA方案. 目前官方提供两种HA方案: 嵌入式DB的高可用( ...

  10. Python学习—Anaconda详细 下载、安装与使用,以及如何创建虚拟环境,不仅仅只有安装步骤哦

    上一期我们介绍了Python.Pycharm.Anaconda三者之间的关系以及使用,这一期主要详细介绍如何在Windows上下载和安装工具Anaconda,然后使用其自带的conda管理不同项目的虚 ...