PHP 实现base64编码文件上传出现问题说明
发布时间:2022-07-18 15:05:41 所属栏目:PHP教程 来源:互联网
导读:这篇文章主要介绍了PHP 实现base64编码文件上传出现问题详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下。 一、场景 领导:小A同学,我们要做一个样本上传进行分析的功能,你看下是否使用base64编码
这篇文章主要介绍了PHP 实现base64编码文件上传出现问题详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下。 一、场景 领导:小A同学,我们要做一个样本上传进行分析的功能,你看下是否使用base64编码加进去,这样客户端的同学就不需要用form-data方式来上传了,直接使用json格式就可以上报,可以让格式上报统一。 PHP 实现base64编码文件上传出现问题详解 本身的流程是一个很简单的文件转换成base64上传,再服务端decode保存,在开发联调过程中没有问题,非常完美的走下去了。 二、问题来了 突然有一天终端同学误操作将一个37M文件上传,nginx与php-fpm文件上传限制均为(60M),但是在界面出现500错误,进入docker 日志查看有一条数据: Allowed memory size of 8388608 bytes exhausted (tried to allocate 1298358 bytes) 三、测验 接下来我们单独写一个程序来进行测试,将一个4.89M文件进行base64_encode 编码 与base64_decode解码,查看各自占用内存以及过程中占用峰值内存 <?php $mid = memory_get_usage(); $apk_content = file_get_contents(__DIR__ . '/4bc1c8a05b8505662be778b6dad23b55.apk'); var_dump('文件加载到内存:' . round((memory_get_usage() - $mid) / 1024 / 1024, 2) . 'M'); var_dump('过程中峰值使用的内存:' . round(memory_get_peak_usage() / 1024 / 1024, 2) . 'M'); unset($mid); $mid = memory_get_usage(); $base64_encode = base64_encode($apk_content);unset($apk_content); var_dump('base64_encode占用内存:' . round((memory_get_usage() - $mid) / 1024 / 1024, 2) . 'M'); var_dump('过程中峰值使用的内存:' . round(memory_get_peak_usage() / 1024 / 1024, 2) . 'M'); unset($mid); $mid = memory_get_usage(); base64_decode($base64_encode); var_dump('base64_decode占用内存:' . round((memory_get_usage() - $mid) / 1024 / 1024, 2) . 'M'); var_dump('过程中峰值使用的内存:' . round(memory_get_peak_usage() / 1024 / 1024, 2) . 'M'); unset($mid); 执行结果: string(29) "文件加载到内存:4.89M" string(38) "过程中峰值使用的内存:5.25M" string(38) "过程中峰值使用的内存:13.4M" 通过上面结果可以看出 加载文件使用内存没有太大问题,加载过程使用的峰值在5.25M,高出整体文件大小不多,这在文件加载过程有一些临时申请内存的问题 base64_encode占用内存,这个在使用的时候,就已经将内存差不多进行一个double,而这基本上也是在内核解析过程中,进行了内存申请,可以理解,文件本身占用内存+base64_encode 解析后的内存,两份内存同时存在的 base64_decode操作,这个操作就是解密了,解密过程中,这里直接就占用了3倍多的内存操作,问题就出在这里,在场景中出现的问题是一个37M的文件,为什么就把单个fpm的128M内存占满了呢 四、源码解析 base64_encode源码解析 首先找到对应的c文件 base64.c,找到里面php_base64_encode函数 PHPAPI zend_string *php_base64_encode(const unsigned char *str, size_t length) /* {{{ */ { result = zend_string_safe_alloc(((length + 2) / 3), 4 * sizeof(char), 0, 0); p = (unsigned char *)ZSTR_VAL(result); ... } 我们先来分析这段代码,因为这里涉及到内存的问题,那么我们就看 result = zend_string_safe_alloc(((length + 2) / 3), 4 * sizeof(char), 0, 0); (编辑:应用网_丽江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |