关于系统的文件上传处理方式
关于系统1.0admin 发布于:2018-06-22 09:50:21
阅读:loading
文件上传是一个老问题了,各个web框架也均对其自己的封装,基本都是在拦截器中实现的。本系统有使用到springmvc,但我并没有使用它包装的文件上传功能(本系统的涉及文件上传功能不多),起初需要加上文件上传功能的是由移动端mui的图片上传图裁切处的功能需求,页面ajax传递来一个图片的base64的字符串,将其转换为图片文件并返回图片地址,后来由于继续深入mui的图片压缩上传(使用uploader组件)和整合simditor时的图片上传(使用input type=file实现)才慢慢的实现了一个文件上传的全局通用处理实现,这里结合我的应用场景来具体说明。
场景1:上传的附件(不限于图片)可以在分布式环境部署中应用,具体描述如下:
上传的文件必须不能放置在应用的某个目录下(如以前有这么干过,直接在工程目录下创建一个upload目录,所有的附件均上传至本应用的目录内),虽然应用可以很方便的直接进行附件的访问,但是如果需要部署多台的服务器时,放置在某一个工程下的附件对于别的工程就无法进行直接访问了。
解决的方案是将附件专门存储于一个公共的目录,所有的应用均可访问(如专门一台设备为文件服务器),上传文件时将附件写入至公共目录,此时访问附件时无法直接使用http请求的方式进行直接访问,需要做转换处理,详细如下:
一、什么是公共目录,如何以公共目录的方式进行访问?
公共目录我这里想描述的是所有应用均可访问的路径,比如我所有的应用均部署在同一台服务器上时,任意一个磁盘路径对于各个应用来讲都属于公共路径,如d:\upload目录;另外一种如果应用部署于多个服务器上时,在windows下可将目录共享出来,直到可以直接使用ip地址访问的情况,如\\192.168.1.7\upload目录,代码里面仍然可以直接使用File对象进行构造的读和写;另外一种较为复杂的就是使用smb协议的共享目录读写访问*作(像我这种小系统第二种方式足够使用了)。
二、附件如何访问?
常规的访问是请求 http://www.chendd.cn/upload/xxx ,如果直接以这种方式的访问则后果是比较严重的,如果别人往upload目录里面上传一个html文件,那么访问这个路径会直接运行html文件,试想如果上传一个jsp文件呢,后果什么都有可能。我的实现是把住文件上传的入口,将所有的附件上传的后缀全部以.image结尾进行存储,也就是说你看到的本站的所有的附件均为.image结尾,包括各类的文件,相关的有.jpg.image,.zip.image,.exe.image等等,由一个全局的servlet专门过滤.image的请求,同时将附件路径的相对地址转换为绝对地址进行转换后的文件访问,最终以ServletOutputStream流write至浏览器上,类似于验证码的图片输出实现。
三、专门处理文件上传servlet包装?
起初文件上传全部是ueditor自带的相关文件上传处理,包括上传图片(单图、多图)、附件等,已经全部给改成.image后缀存储了,后面又由于移动端的需要故实现了一个全局的附件上传包装实现,使用apache的common-fileupload组件实现,相关的逻辑分别是:
1)用户请求的合法性校验,主要是移动端的使用故验证用户传递的token是否有效;
2)根据用户需求是否进行图片的缩放(一般手机端的图片都特别大2M-3M是常用的事情),如果直接传输访问这么大的图片显然不科学,缩放的图片比例由系统定义,如我设置了30x30,60x60,128x128,300x300,原图等,都是由设置了宽度或高度后进行按比例缩放采用thumbnailator组件实现;
3)访问图片时如果参数中有width属性,则优先输出附件缩放至大小的宽高进行访问,如不存在则输出附件名称的文件;
4)含有uploading参数可支持文件上传的进度信息,可实现进度条效果,需要定时刷新的配合;
四、文件上传功能附有业务功能处理?
支持service参数,如果在上传文件的同时含有业务功能处理可通过传递service的方式实现,系统会先处理附件上传,如果附件上传出现错误则直接返回相应的错误提示信息,否则附件上传完毕后进行service参数处理,传递的值为spring组件的beanName,然后通过调用其实现类的execute函数进行处理;
以上文章属于想到哪写到哪的,至于代码与我这系统目前的耦合度较深,贴出来意义不大,上述思路是重点,那就这样吧。
点赞