网站上传图片

这行代码,网站可能是上传很多前端新手最早学会的魔法之一。但真正把一张照片从手机挪到网页上,图片远比这行代码复杂得多。网站我上周刚帮朋友调试一个电商网站,上传他上传商品图时总报错,图片折腾两小时才发现是网站图片尺寸超了5MB——浏览器直接罢工,连个像样的上传提示都没给。 图片上传的图片本质,是网站文件从本地到服务器的搬运。但搬运之前,上传你得先过三道关卡:格式、图片大小、网站命名。上传格式上,图片PNG、JPG、WebP是主流,GIF动图另说。大小?别信“无限上传”的鬼话,服务器资源有限,你传个20MB的RAW格式照片,服务器得哭。命名更坑,中文文件名、带空格的文件名,传到某些老旧服务器上直接乱码,甚至被当成非法字符拒绝。 真正的坑在传输过程。HTTP协议传输文件,要么用form表单的multipart/form-data,要么用AJAX的FormData对象。前者是传统手艺,页面会刷新;后者是新时代玩法,能配合进度条、多文件并发。但无论哪种,一旦网络抖动,上传就可能中断——这时候断点续传就派上用场了。可惜很多初级开发压根没考虑这层,用户上传到99%突然失败,只能重头再来,这体验,搁谁谁不骂娘? 服务器端也不是省油的灯。你收到文件流,得先校验MIME类型——别信前端传的content-type,用PHP的finfo或Node的file-type去读文件头,才能识别真实格式。有人改个扩展名就想蒙混过关?文件头会出卖他。校验完格式,还得限制尺寸和大小。用getimagesize()或sharp库读图片宽高,超过设定值就压缩或拒绝。我见过一个后台系统,上传图片不压缩直接存原图,半年后硬盘爆了,运维骂街骂了三天。 最容易被忽视的是存储路径。把上传的图片直接丢进web根目录?等着被爬虫扫吧。正确做法是存到项目外的独立目录,通过路由或符号链接访问。文件名也别用用户原名,随机生成一串哈希值,既避免冲突,又能防止路径穿越攻击——有人传个文件名是“../../etc/passwd”,你要是不处理,服务器就裸奔了。 图片上传成功后,还有个隐藏环节:生成缩略图。列表页用100x100的小图,详情页用800x600的中图,原图只在点击放大时加载。不这么做,一个页面加载20张高清图,用户手机直接卡死。用ImageMagick或sharp库,上传时同步生成三份不同尺寸的文件,虽然占点存储,但换来的流畅体验绝对值。 最后说个我踩过的坑:上传超时。默认配置下,PHP的max_execution_time是30秒,Nginx的proxy_read_timeout是60秒。传大文件时,前端等得花儿都谢了,后端却已经把请求掐断了。解决办法是把超时时间调大,或者改用分片上传——把100MB的文件切成10MB的块,逐块传,失败只重传失败的那块。 上传图片这事,看着简单,实则每个环节都能让你崩溃。但反过来想,当你把这一整套流程理清楚,图片从点击到显示,三秒内完成,用户毫无察觉,那种成就感,比写一百行业务代码都爽。