RJ博客

从PHP接收接收二进制图片,延伸至文本文件和二进制文件异同

本文目录

###背景:

以前知道有一种把二进制图片数据直接保存到数据库的做法,不过一直没实际操作 过,直到在对接广告Marketing API传输图片原数据要用到,才去深入地了解了一下。


###实践:

这里有个简单例子:

HTML:

blob.png

PHP:

function imgApp()
{
    //方式一:电脑上传文件
    $p_w_picpath = $_FILES["photo"]["tmp_name"];
    $fp          = fopen($p_w_picpath, "r");
    $file        = fread($fp, $_FILES["photo"]["size"]); //二进制数据流
    //保存地址
    $imgDir = './Uploads/';
    //要生成的图片名字
    $filename    = date("Ym") . "/" . md5(time() . mt_rand(10, 99)) . ".png"; //新图片名称
    $newFilePath = $imgDir . $filename;
    $data        = $file;
    $newFile     = fopen($newFilePath, "w"); //打开文件准备写入
    fwrite($newFile, $data); //写入二进制流到文件
    fclose($newFile); //关闭文件
}

除了用fread(),直接用file_get_contents()也可以获取到二进制数据。

以上是把接收到的二进制图片转换成图片文件保存起来,也可以把二进制数据存入 数据库,mysql数据库中BLOB是一个二进制对象,能容纳不同大小的数据。BLOB类型有以下四种,除存储的最大信息量不同外,其他都是一样的:

BLOB类型可存储文件大小
TinyBlob最大 255B
Blob最大 65K
MediumBlob最大 16M
LongBlob最大 4G

从数据库取二进制数据展示成图片可参考:

https://www.cnblogs.com/qingsong/p/4910090.html


但是如果是要通过http接口以json格式传输数据,直接二进制是传不了的,因为json 是一种很简洁的协议,但可惜的是,它只能传递基本的数型(int,long,string等),但不能传递byte类型。如果想要传输图片等二进制文件的话,是没办法直接传输。不过处理方法还是比较多的:Base64,十六进制表示法,‘\0′ 字符反转义都可行。Base64最为普遍,并且前端也支持Base64数据格式的图片。

Base64编码如下:

$binary = file_get_contents($pic_path);
$base64 = base64_encode($binary);

举个图片的例子,网页中一张图片可以这样显示:

<img src="http://nearby.wang/Public/Images/logo-icon.png"/>

也可以把图像文件的内容直接写在了HTML文件中,取数据的时候记得在前面拼接:

data:image/png;base64,

其中,data表示取得数据的协定名称,image/png 是数据类型名称,base64 是数据的编码方法,逗号后面就是这个image/png文件base64编码后的数据。

<img src="data:image/png;base64,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"/>

如果仅从加载速度上来说,小图片使用base64毫无疑问会更快,因为可以减少一次http请求,但是如果图片较大,转换后的base64会更大,浏览器解析需要更长的时间,有可能会造成页面阻塞,效率上应该不如直接放图片,而且使用base64无法缓存(除非直接缓存整个文件,例如写到css文件中)。

如果取出的Base64数据要换成成图片保存到本地,则需要对Base64解码保存(不需要加 data:image/png;base64,):

file_put_contents("logo-icon.png", base64_decode("Base64二进制数据"));

至此,二进制图片就讲完了。


最后还有一个疑问,就是为什么二进制数据看起来是乱码的?像这样:

blob.png

这里要引入文本文件与二进制文件的概念,广义的二进制文件即指文件,由文件在外部设备的存放形式为二进制而得名。狭义的二进制文件即除文本文件以外的文件。

文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等等。二进制文件是基于值编码的文件。

狭义上的二进制文件与文本文件的比较:

1.能存储的数据类型不同文本

  文件只能存储char型字符变量。二进制文件可以存储char/int/short/long/float/……各种变量值。

2.每条数据的长度文本文件每条数据通常是固定长度的。

  以ASCII为例,每条数据(每个字符)都是1个字节。进制文件每条数据不固定。如short占两个字节,int占四个字节,float占8个字节……

3.读取的软件不同文本文件编辑器就可以读写。

  比如记事本、NotePad++、Vim等。二进制文件需要特别的解码器。比如bmp文件需要图像查看器,rmvb需要播放器等。


所以当打开二进制文件时,出现乱码也是很必然的一件事情了,解码和译码不对应嘛。例如文件流''00000000_00000000_00000000_00000001''可能在二进制文件中对应的是一个四字节的整数int 1,在记事本里解释就变成了"NULL_NULL_NULL_SOH"这四个控制符。


二进制文件的编辑和查看,需要下载二进制编辑器才能查看,如果是Linux系统,可以使用vim。

(1)打开文件:

vim -b file

(2)转换为十六进制:

:%!xxd

文本看起来像这样:

0000000: 1f8b 0808 39d7 173b 0203 7474 002b 4e49 ....9..;..tt.+NI

0000010: 4b2c 8660 eb9c ecac c462 eb94 345e 2e30 K,.`.....b..4^.0

0000020: 373b 2731 0b22 0ca6 c1a2 d669 1035 39d9 7;'1.".....i.59.

保存退出再重新打开,现在你可以随心所欲地阅读和编辑这些文本了。Vim 把这些信息当作普通文本来对待。修改了十六进制部分并不导致可显示字符部分的改变,反之亦然。

(3)转换回二进制:

:%!xxd -r

只有十六进制部分的修改才会被采用。右边可显示文本部分的修改忽略不计。

xxd是linux的一个命令,vim可以通过”!”来调用外部命令,其功能就是进行十六进制的dump或者反之。


扩展:

如果需要读大量的数据,数据都是txt格式的,读的过程会比较慢,为了加快读取的速度,可以将文本文件转为二进制文件:

https://blog.csdn.net/wh357589873/article/details/51700482



Refer:

https://blog.51cto.com/caixia/1712393

https://blog.51cto.com/31329846/1844150

https://segmentfault.com/q/1010000007009081/a-1020000007012411

https://blog.csdn.net/ithover/article/details/78681559

https://blog.csdn.net/yjclsx/article/details/84285757

https://blog.csdn.net/liuhongwei_study/article/details/41120443

https://www.jianshu.com/p/af0b4f8b030e

https://blog.csdn.net/wangxiaoqin00007/article/details/6618003




相关推荐

发表评论