php上传图片到非项目目录,前端页面的读取问题

一、前言

      关于上传文件部分的危险,一直以来都有听说,但是之前为了方便,一直都是直接放到项目根目录,方便访问。只是现在项目越来越大,安全问题虽然不用刻意追求,但这些基本的地方还是要注意一下的。上传的路径最好是项目不能直接访问到的。

PHP 安全:如何防范用户上传 PHP 可执行文件

      如链接文章所言,现在的jpg里面也能编辑一些代码,所以上传的路径最好是项目不能直接访问到的。比如项目B在:/soft/www/B,那么文件最好上传到/soft/www/images 这样的话,外界不能通过域名直接访问,会比较安全。包括下载的excel,csv等文件,涉及到上传下载的部分都应该注意。

二、图片的访问问题

      是的,我们成功的把图片上传到了非项目目录,我们已经预防了黑客们的一次进攻,lets cheers。正在博主高兴的时候,前端展示图片的页面突然出问题了。是的,原来我们都是通过路径直接找到图片存储的位置,可是现在根本就无法通过路径去找到它。。。

1、直接绝对路径,试试文件协议访问

直接拼接地址,想要在本地直接看:C/project/images/aaa.png

答案: 这样访问不到,因为imgsrc默认是http协议的,而我们这种写法是file协议的,所以无法在网页上直接访问

2、使用js直接访问本地图片,然后转化为base64显示?

答案: 不可以,浏览器出于安全考虑,不允许web直接访问用户的文件系统。除非用input标签,或者小程序的平台(比如微信)有提供相应的接口。存储数据,微信有wx.setStorageH5有localstorageIndexedDB
在网上搜素的大部分答案都是需要用inputfile文件上传来获取file对象,我们这里不需要使用input的上传标签,所以我在试了好几种方法之后无奈放弃

3、考虑写入文件,由JS读取文件

这个方案是在存储图片的时候,顺带存储一份base64到文件吗,由JS读取文件。

缺点:
(1)由JS读取文件,那么php每次刷新页面,文件都要重写
(2)js读取之后,要在首先进行拆分,其次是按照id来拿到base64,最后赋值给img,性能上可能会慢很多,而且写入文件的话,会存在文件锁的问题,如果是多人访问的系统,尽量还是不要这么做。
(3)其次是写入的json,为了让js能读取到,那势必要放入到可访问目录的,通过ajaxurl去访问json文件,
      ajax是让js能主动发起http请求,达到不需要跳转url就能发起请求拿到数据,那么意味着这个json文件在浏览器上也是可访问的,这样的话为什么咱们不把图片直接上传到项目目录下呢?既然不准备上传到项目目录下,那用这个json文件貌似也没意义。
(4)这个方案已经放弃,但是关于js读取文件还是可以学习的

js读取text文件:https://blog.csdn.net/qq_37338983/article/details/81567542
				js读取json文件:	var configure_json = $.ajax({url: “./json/configure.json”,async: false}).responseText;
						var configure_json_val = $.parseJSON(configure_json);
						alert(configure_json_val[0].holiday);
	
				php使用file_get_contens写入json到json文件:	https://zhidao.baidu.com/question/235095737.html
							类似的方法:	https://www.douban.com/note/710707937/
				如果输出到页面JS接收,要注意编码一定要utf-8(json_encode 默认的就是utf-8编码)

4、使用基类直接生成随略图存起来

      直接生成缩略图的话,最后还是避不开存储的问题。如果还是存储在项目内部,那其实是没有起到安全的作用。存在项目外的话,照样是能直接访问的。不过相对于直接上传文件存在项目内部,缩略图能稍微安全点。其次就是需要存储在数据库,要是用额外的字段去存储它。
具体的仁者见仁智者见智吧,感觉不是很好,并没有避过上面提出的安全问题。

三、最终方案

      想来想去,为了能成功访问到图片,并且避免跨域问题,尽量是转化为base64返回。既然使用JS无法达到目的,那就只能继续磨练我们的php了。

(1)php转化图片路径为base64

生成缩略图基类下载地址:链接: https://pan.baidu.com/s/1L_C4hmmF-iLRrKcfyb13wA 提取码: h8yk
获取图片流并生成base64码:参考:https://blog.csdn.net/LJFPHP/article/details/79111844
php代码:

							 $img_path = $dir.$images;  // 图片的哭啼路径
                    			$thumb = new Thumbnail(100, 100); //设置缩略图大小为100*100
                    			ob_start();		//开启缓冲,获取图片流
                    			$thumb->loadFile($img_path);
                    			$thumb->buildThumb();
                    			$imageString = base64_encode(ob_get_contents());  //把获取的图片流转化为base64编码
                    			ob_end_clean();
                    			$base64_image = 'data:' .$thumb->getMine() . ';base64,' .$imageString;  //拼接图片需要的base64格式

(2)js匹配id,给图片的src赋值

js代码:
				  if (data.code === "200") { //请求成功就进行赋值
               					 if(data.images.length > 1){
                    				$("#preview").css("display","block");  //图片显示
                    				$("#portrait").attr("src",data.images); //给图片的src赋值
               				 	}
            				}

这样我们终于可以在前端页面上展示了我们的图片:

在这里插入图片描述
问题:
(1)页面上的base64可能会有几十个,占用大量的页面的资源,感觉是不好。
(2)其次是图片越大,最后生成的base64就越长,
(3)当base64很长的时候,也会影响到页面的加载速度。
(4)在页面加载之处,就把这些图片转化的base64都传输到页面上,本身反应速度也会受到影响

相关优化:
(1)使用一个生成缩略图的基类
(2)使用基类把图片生成较小的缩略图,然后直接把生成的图片流转化为base64的文件流,然后拼接返回给前端页面
优点:可以通过缩略图控制图片的大小,缩略图的图片小了之后,生成的base64码也少了,不会很影响加载速度
缺点: (1)页面上还是会有一部分显示base64的地方
(2)当页面上的base64码很多的时候,会影响页面的加载速度。这部分我们可以通过分页来避免一下

虽然我们的图片是展示出来了,但是速度实在堪忧。需要继续优化。

优化篇:
网页上的base64码太长?科普base64到底是啥

end

首先,需要在数据库中创建一个表来存储PDF文档,例如: ``` CREATE TABLE pdf_documents ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), content LONGBLOB ); ``` 然后,在PHP前端中,可以使用HTML的表单来实现上传PDF文档的功能。例如: ``` <form action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" name="pdf_file"> <input type="submit" value="Upload"> </form> ``` 接下来,需要编写一个PHP脚本来处理上传操作。在该脚本中,首先需要验证上传的文件是否为PDF文档,然后将该文档的内容读取到一个变量中,并将该变量存储到数据库中。例如: ``` <?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { $pdf_file = $_FILES['pdf_file']; $pdf_name = $pdf_file['name']; $pdf_tmp_name = $pdf_file['tmp_name']; $pdf_type = $pdf_file['type']; if ($pdf_type != 'application/pdf') { echo 'Only PDF files are allowed'; exit; } $pdf_content = file_get_contents($pdf_tmp_name); $dsn = 'mysql:host=localhost;dbname=my_database'; $username = 'my_username'; $password = 'my_password'; try { $pdo = new PDO($dsn, $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $pdo->prepare('INSERT INTO pdf_documents (name, content) VALUES (:name, :content)'); $stmt->bindParam(':name', $pdf_name); $stmt->bindParam(':content', $pdf_content, PDO::PARAM_LOB); $stmt->execute(); echo 'File uploaded successfully'; } catch (PDOException $e) { echo 'Error: ' . $e->getMessage(); } } ?> ``` 最后,在PHP网页中,可以查询数据库中的PDF文档,并将其显示在页面上。例如: ``` <?php $dsn = 'mysql:host=localhost;dbname=my_database'; $username = 'my_username'; $password = 'my_password'; try { $pdo = new PDO($dsn, $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $pdo->query('SELECT * FROM pdf_documents'); while ($row = $stmt->fetch()) { $pdf_name = $row['name']; $pdf_content = $row['content']; echo '<a href="data:application/pdf;base64,' . base64_encode($pdf_content) . '">' . $pdf_name . '</a><br>'; } } catch (PDOException $e) { echo 'Error: ' . $e->getMessage(); } ?> ``` 以上就是将PDF文档通过PHP前端上传数据库,并在PHP网页中读取该文档的方法的示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁柱同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值