原创

关于项目中文件上传

温馨提示:
本文最后更新于 2020年12月09日,已超过 1,400 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

在项目中,我们难免会遇到要上传文件的需求,例如头像,文章图片,等等相关的文件需求,那么如何才能做好文件上传呢?我将从 上传方式,存储方式等几个方向来做说明.

跟随表单上传

跟随表单上传是我们最早接触的一种上传方式了

<html>
<body>

<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>

它要求 form表单 的 是 multipart/form-data形式.

浏览器将会渲染 input type=file的输入框作为选择文件,选择成功之后

只需要点击提交,文件即可和表单的其他内容一同上传

这个做法在前后分离之后,就基本很少见了.

新版的跟随表单上传,通过了ajax 形式进行一次性提交

跟随表单的做法目前还有,但是已经越来越少了

优点是每次都随着自己的业务表单提交,不会出现垃圾文件

缺点是如果文件太大,提交表单的时间将会很长,而且看不到进度

异步上传

为了解决提交表单时文件太多/太大,导致提交表单的时间延长,开发者采用了新的方式进行上传,也就是 异步上传

表单还是原来的表单,在选择文件之后,前端将会立即请求另一个 文件上传的接口,直接将文件上传.同时返回文件上传后的路径交给前端的表单

在提交表单时,前端只需要将文件路径提交即可.

优点是 用户体验非常好,表单提交很快,同时将文件上传的逻辑跟表单保存逻辑分离,便于修改管理

缺点是 在用户选择完之后,如果此表单没有提交,这个文件就会成为垃圾文件一直存储在服务器中.

垃圾文件解决方案

异步上传的垃圾文件解决方案如下:

- 用户上传文件到临时文件夹(/temp/)

- 用户提交表单之后,从临时文件夹移动文件到新目录中,表示该文件有效

- 如果用户是更新表单,从临时文件夹移动文件到新目录,同时删除原有文件

存储方式

一般情况下,为了方便,我们通常都是直接将文件存储到本地服务器中,直接通过nginx代理获取文件

这样的做法优点是管理文件方便,实现简单,缺点是会占用服务器的带宽,使得带宽成本上升.

为了节省服务器带宽,可以直接使用 oss(对象存储) 服务,使用阿里云/腾讯云对象存储进行存储文件

用户访问也是直接访问 oss 不需要占用服务器的带宽,节省服务器带宽成本

文件路径存储

一般情况下,我们都是存储文件的相对路径,例如:"./Upload/avatar/1.jpg"

如果是通过服务器存储的话,在网页中浏览器会自动加上当前域名进行访问文件 :"http://www.php20.cn/Upload/avatar/1.jpg"

但是如果通过oss存储方案的话,很明显,直接存储相对路径的话,没法直接访问,但是存储绝对路径的话,如果阿里云oss域名改了,或者说服务器迁移了,就会造成原先数据全部不能使用,那该怎么解决这个问题呢?

解决 oss 存储路径的问题

我们可以通过 存储相对路径+取出数据额外组装数据的方式实现oss文件的存储.

例如:oss host为:"http://oss.xxx.aliyunoss.com/",文件路径为:"./Upload/avatar/1.jpg"

在数据库中只存储相对路径,然后在获取数据时,获取到oss host 数据,进行拼接组装,即可解决此问题.

前端二次更新表单解决方案

在刚刚的oss 存储绝对路径的时候,又引来了新的问题

当第一次上传的时候,前端提交的是"./Temp/avatar/1.jpg"(临时路径+复制文件到新路径)  一个绝对路径

如果前端需要编辑,更新表单,会因为 后端额外拼接组装了数据,而导致下次提交变成了 "http://oss.xxx.aliyunoss.com/./Upload/avatar/1.jpg";这个时候存储路径则额外增加了 一个host.

所以我们需要在更新文件路径时做好判断,具体步骤如下:

1:第一次上传,temp/xx.jpg

2:判断该路径是否为 "temp/"前缀开头,如果是,则代表是临时文件,代表修改了文件

3:将临时文件复制一份正式文件"Upload/avatar/1.jpg",存储到数据库

4:前端获取信息时,后端自动拼接:"http://oss.xxx.aliyunoss.com/Upload/avatar/1.jpg"

5:第二次提交,不更新文件路径,则将提交:"http://oss.xxx.aliyunoss.com/Upload/avatar/1.jpg" 通过第二步的判断,表示此文件不是临时文件,则不做文件路径更新

6:第二次提交,更新文件路径,则将提交 :"temp/xx.jpg",由于第二点的判断,则将复制一份正式文件 "Upload/avatar/2.jpg",存储到数据库

7:同时删除原来数据库存储的 "Upload/avatar/1.jpg" 文件

正文到此结束
本文目录