分离文件服务器-文件上传
做了接近两年的外包,如今回归到做公司自己的产品,不同的工作模式就会有不同的系统设计,先看一组图:
与前者相比,后者在应用层和展现层做了更清晰的划分,好处不可描述。但随之而来的问题是不同站点间的文件上传混乱不易管理,于是分离出文件服务器,统一文件的上传、访问、管理。下面是我在分离文件服务器过程中遇到的一些问题以及解决方案(以图片为例)。
图片上传配置
图片上传配置包括限制上传的图片类型、图片大小、图片尺寸、以及水印类型、水印文件位置等等。具体可按自己的需求进行配置,并不局限于此。
{ "ImageTypeLimit": "gif,jpg,png,bmp,jpeg", "ImageSizeLimit": 51200, "ImageWidthLimit": 1200, "ImageHeightLimit": 1200, "WatermarkType": 2, "WatermarkPosition": 303, "WatermarkAddress": "F:\\shuiyin.png", "WatermarkWords": "liuxx", "WatermarkWordsFont": "Verdana", "WatermarkWordsFontSize": 12, "WatermarkTransparency": 8 }
由于系统还很稚嫩,也没有传说中所有站点通用的配置中心,那么后台系统需要对文件服务器配置进行管理的方式大概有两种:
1、配置数据存储在数据库,提供给这两个站点同时访问。
2、配置数据独立存储于文件服务器,管理站点通过接口获取以及修改。
因为现阶段我们对于图片管理的需求不是很强烈,整个文件服务器几乎都没有与数据库打交道的需求,所以我们选择了第二种方式。至于通过接口修改配置的安全性,我们使用的是ip白名单限制。
跨域上传文件
跨域上传文件主要涉及到ajax跨域上传文件以及ueditor跨域。跨域请求时浏览器会首先发送一次options嗅探,同时header带上origin,判断是否有跨域请求权限,服务器响应access control allow origin的值,供浏览器与origin匹配,如果匹配则正式发送post请求。
知道原理解决起来就方便多了,两个步骤:
1、在webconfig中添加:
<httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="POST, PUT /> </customHeaders> </httpProtocol>
2、在Global.asax中添加代码处理浏览器发起的options请求:
protected void Application_BeginRequest(object sender, EventArgs e) { var req = System.Web.HttpContext.Current.Request; if (req.HttpMethod == "OPTIONS")//过滤options请求,用于js跨域 { Response.StatusCode = 200; Response.SubStatusCode = 200; Response.End(); } }
我们的文件上传使用的是webapi,mvc和webform应该也可以使用相同的方式,或者选择第三方库如:Microsoft.AspNet.WebApi.Cors来处理,有兴趣的可以自己尝试,我觉得没那么麻烦也就没有继续折腾。
关于ueditor将上传的文件保存在文件服务器,最简单的方式是将ueditor直接部署在文件服务器,然后使用域名引入js,如果上传还是出现跨域问题,并且文件服务器和使用ueditor的网站根域名相同,可按下面两个步骤进行解决:
1、在文件服务器中ueditor/dialogs/internal.js顶部添加代码:document.domain = "根域名";
2、在引用ueidtor的页面顶部js中添加document.domain = "根域名";
最后,ueditor的单图上传死活跨域上传失败,对着源码折腾了四个小时无果,解决了跨域显示出问题,解决了显示跨域又不行,后面看到官方文档上的说明后
也就暂时放弃了,有兴趣的朋友可以尝试一下。
文件保存
上传文件的保存基本上人人都会,对于webapi文件上传有疑惑的可以参考这篇博客,讲的非常详细了:http://www.cnblogs.com/ang/archive/2012/10/24/2634176.html。
拿到上传的文件后要做的事情就是根据自己的文件上传配置做验证,过滤非法的文件并对图片做处理,如图片添加水印、生成缩略图等等。网上代码有很多,并且每个系统对于水印和缩略图的需求会不相同,这里就不贴代码了。比如我们的就有两个比较有意思的需求:
1、水印图片是按照800*600的背景图做的,要求对上传的图片按最小的长宽比对水印进行缩放后再添加到图片上。
2、图片访问时根据前端提供的合法参数自动生成缩略图并保存,下次访问直接返回缩略图。这个我会在下一篇博客中具体介绍我的思路以及最后的实现方式。
顺便提一下对ueditor上传的图片进行处理(如:打水印),网上也有不少相关的帖子,大概思路无非就是重写图片上传的路径,然后再按ueditor的格式返回数据(在xx版本所有文件上传统一为一个路径之后,这个方式做起来就不是那么优雅了)。我们的做法是:嗯~~~,改源码。步骤也很简单:
1、ueditor/net/controller.ashx中的配置改为从我们的上传配置中读取。
2、ueditor/net/App_Code/UploadHandler.cs中文件保存时做处理。
看了ueditor文件上传的服务端代码,对于文件上传又有了新的认识,其实可以抛开所谓webform、mvc、webapi的区别,直接使用IHttpHandler处理上传的图片流,简单直接又粗暴得无可挑剔。