框架:jsp + springMVC + Tomcat
前台使用
elfinder
这是一个很好用的开源web文件管理器插件,用jquery+jquery-ui写的,在网上一搜文档好像也挺多的,于是准备搬到项目中来(挖坑开始),了解过后发现作者附带的后台demo是php写的,大多文档资料也是php的,java的特别少,出了问题也不知道是为什么,急死个人,前后折腾了两天才勉强能用了,在这里记录一下,以供大家参考,本人菜鸟,如果有什么理解不对的地方,欢迎各位指正。
打开官网,把代码dow下来:
打开压缩包:把选中的这些文件拷到项目中:
选中的可能有用,没选中的肯定没用(为什么?因为这没拷进项目里他也能跑,而且没问题...)
后台使用的是一个大神开源的基于java实现demo
elfinder-2.x-servlet
这个目前还在持续更新中
接下来开始配置吧,基础版:
Maven项目中添加依赖项
1 <!-- web文件夹管理器jar包 -->
2 <dependency>
3 <groupId>com.github.bluejoe2008</groupId>
4 <artifactId>elfinder-servlet-2</artifactId>
5 <version>1.2</version>
6 <classifier>classes</classifier>
7 </dependency>
或者直接点击下载
elfinder-servlet-2.jar
包放到lib目录下
接下来在servlet.xml中配置需要spring管理的各对象
1 <!-- find appropriate command executor for given command-->
2 <bean id="commandExecutorFactory"
3 class="cn.bluejoe.elfinder.controller.executor.DefaultCommandExecutorFactory">
4 <property name="classNamePattern"
5 value="cn.bluejoe.elfinder.controller.executors.%sCommandExecutor" />
6 <property name="map">
7 <map>
8 <!--
9 <entry key="tree">
10 <bean class="cn.bluejoe.elfinder.controller.executors.TreeCommandExecutor" />
11 </entry>
12 -->
13 </map>
14 </property>
15 </bean>
17 <!-- FsService is often retrieved from HttpRequest -->
18 <!-- while a static FsService is defined here -->
19 <bean id="fsServiceFactory" class="cn.bluejoe.elfinder.impl.StaticFsServiceFactory">
20 <property name="fsService">
21 <bean class="cn.bluejoe.elfinder.impl.DefaultFsService">
22 <property name="serviceConfig">
23 <bean class="cn.bluejoe.elfinder.impl.DefaultFsServiceConfig">
24 <property name="tmbWidth" value="80" />
25 </bean>
26 </property>
27 <property name="volumeMap">
28 <!-- two volumes are mounted here -->
29 <map>
30 <entry key="A">
31 <bean class="cn.bluejoe.elfinder.localfs.LocalFsVolume">
32 <property name="name" value="MyFiles" />
33 <property name="rootDir" value="/tmp/a" />
34 </bean>
35 </entry>
36 <entry key="B">
37 <bean class="cn.bluejoe.elfinder.localfs.LocalFsVolume">
38 <property name="name" value="Shared" />
39 <property name="rootDir" value="/tmp/b" />
40 </bean>
41 </entry>
42 </map>
43 </property>
44 <property name="securityChecker">
45 <bean class="cn.bluejoe.elfinder.impl.FsSecurityCheckerChain">
46 <property name="filterMappings">
47 <list>
48 <bean class="cn.bluejoe.elfinder.impl.FsSecurityCheckFilterMapping">
49 <property name="pattern" value="A_.*" />
50 <property name="checker">
51 <bean class="cn.bluejoe.elfinder.impl.FsSecurityCheckForAll">
52 <property name="readable" value="true" />
53 <property name="writable" value="true" />
54 </bean>
55 </property>
56 </bean>
57 <bean class="cn.bluejoe.elfinder.impl.FsSecurityCheckFilterMapping">
58 <property name="pattern" value="B_.*" />
59 <property name="checker">
60 <bean class="cn.bluejoe.elfinder.impl.FsSecurityCheckForAll">
61 <property name="readable" value="true" />
62 <property name="writable" value="false" />
63 </bean>
64 </property>
65 </bean>
66 </list>
67 </property>
68 </bean>
69 </property>
70 </bean>
71 </property>
72 </bean>
这里配置就是服务器上的文件夹名称,服务器上是在你有tomcat所在盘的根目录下建一个叫tmp的文件夹,但在客户端(浏览器)上显示的就是你配置的名称:MyFiles
加载jar包后,为了查看后台接收数据的url,需要加载源文件(我给的jar包压缩包里)
我们打开这个类cn.bluejoe.elfinder.controller.ConnectorController可以看到映射路径为”connector”,这就是前台请求后台时的url路径(先暂时记住)
看到这里的@controller,说明这就是后台的接收所有请求的入口,要让springmvc管理这个类,我们需要在springmvc-servlet.xml中加入这个类所在包的扫描
<context:component-scan base-package="cn.bluejoe.elfinder.controller" />
接着开始写前台页面(我用的是jsp页面):
可以直接拿elfinder那个包里的elfinder.html改,但他里面没有引入js和css,所以还是自己来写吧
最好按照下面给出的顺序导入,因为在最开始我没有注意,导致很多样式是乱的,响应到了错误的地方
导入jquery.js,版本稍高的好,因为我发现他的里面用的是jquery-3.*的版本,这个根据自己的路径来导
<script src="${pageContext.request.contextPath}/js/jquery-3.2.1.min.js" type="text/javascript" charset="utf-8"></script>
导入jquery-ui.js jquery-ui.css ,接下来的这些文件的路径都是根据最开始拷到项目中的elfinder包里去找
<link href="${pageContext.request.contextPath}/elfinder/jquery/jquery-ui-1.12.0.css" rel="stylesheet" type="text/css" media="screen" charset="utf-8">
<script src="${pageContext.request.contextPath}/elfinder/jquery/jquery-ui-1.12.0.js" type="text/javascript" charset="utf-8"></script>
导入elfinder.css、theme.css
<link rel="stylesheet" href="${pageContext.request.contextPath}/elfinder/css/elfinder.min.css" type="text/css" media="screen" charset="utf-8">
<link rel="stylesheet" href="${pageContext.request.contextPath}/elfinder/css/theme.css" type="text/css" media="screen" charset="utf-8">
导入elfinder.js
<script src="${pageContext.request.contextPath}/elfinder/js/elfinder.min.js" type="text/javascript" charset="utf-8"></script>
导入中文语言包elfinder.zh_CN.js,elfinder是支持国际化的,从2.0版本开始可以完美支持中文了,如果这里不导入,不配置,默认是英文的
<script src="${pageContext.request.contextPath}/elfinder/js/i18n/elfinder.ru.js" type="text/javascript" charset="utf-8"></script>
<script src="${pageContext.request.contextPath}/elfinder/js/i18n/elfinder.zh_CN.js" type="text/javascript" charset="utf-8"></script>
在html标签中声明容器:
<div id="elfinder" ></div>
Js代码:
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$('#elfinder').elfinder({
url : '${pageContext.request.contextPath}/connector', //这里的请求地址对应controller中的地址
lang : 'zh_CN', //配置默认语言为中文
height : parseInt(window.screen.availHeight * 0.7) //配置高度为浏览器高度的0.7
</script>
此时启动项目应该能看到以下页面了
此时一个坑出现了,我传什么文件都提示“未知的命令:null”,以及后台提示:unknown command:null, google了几个小时才发现是因数servlet.xml中配置了
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8" />
<property name="maxUploadSize" value="104857600" />
<property name="maxInMemorySize" value="2048" />
</bean>
两个冲突了,去掉CommonsMultipartResolver就可以,但是项目中其他地方用到的上传就无法使用了,度娘了很久说冲突可以写一个代理来解决(不太会),直接把别人的代码拿来(好几百行),发现并没卵用,气死个人,于是又开始疯狂搜索...
最后发现根本不用什么代理,CommonsMultipartResolver这个类中有一个
public
boolean
isMultipart
(HttpServletRequest request)方法,我们继承这个类,重写这个isMultipart方法返回true和false就可以达到是否使用这个类来处理上传了
此处使用拦截器来判断其是我们的elfinder的上传文件或是其他上传方式,这里主要是用请求url的方式来判断是否为elfinder的请求,分三个类,代码如下:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class MultipartContextFileter implements Filter {
FilterConfig config;
@Override
public void destroy() {
@Override
public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain chain)
throws IOException, ServletException {
boolean isData = false;
HttpServletRequest req = (HttpServletRequest)srequest;
// 根据web.xml中的配置,判断当前url是否跳过此过滤器
String excludeURL = config.getInitParameter("excludeURL");
if (excludeURL != null && !"".equals(excludeURL)) {
if (req.getRequestURI().indexOf(excludeURL) != -1) {
isData = true;
if (isData) {
String content_type = req.getContentType();
if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
MyMultiPartRequest jakarta = new MyMultiPartRequest(req);
jakarta.isData = true;
req = jakarta;
chain.doFilter(req, sresponse);
@Override
public void init(FilterConfig arg0) throws ServletException {
config = arg0;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* 继承request,对其进行包装,以保存更多信息,用于保存判断是否是elfinder的请求,后面执行时可以判断是否跳过CommonsMultipartResolver的处理
*/
public class MyMultiPartRequest extends HttpServletRequestWrapper {
public boolean isData = false; //是否执行自定义的CommonsMultipartResolver
public MyMultiPartRequest(HttpServletRequest request) {
super(request);
public class CommonsMultipartResolver extends org.springframework.web.multipart.commons.CommonsMultipartResolver {
* 这里是处理Multipart http的方法。如果这个返回值为true,那么Multipart http
* body就会MyMultipartResolver 消耗掉.如果这里返回false
* 那么就会交给后面的自己写的处理函数处理例如刚才elfinder请求
@Override
public boolean isMultipart(HttpServletRequest request) {
if(request instanceof MyMultiPartRequest){
MyMultiPartRequest trequest = (MyMultiPartRequest)request;
if(trequest.isData){
return false;
return super.isMultipart(request);
然后在web.xml中配置拦截器,使其生效
<filter>
<filter-name>MultiPartFilter</filter-name>
<filter-class>com.sctbyc.sware.controller.resourceLibrary.filter.MultipartContextFileter</filter-class>
<init-param>
<param-name>excludeURL</param-name>
<param-value>connector</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MultiPartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
当然也不要忘记把自己刚刚写的处理文件上传的类配置到xml中,这样就spring就会自动创建及调用我们写的这个类了
<bean id="multipartResolver" class="我们定义的CommonsMultipartResolver这个类的全路径名">
<property name="defaultEncoding" value="UTF-8" />
<property name="maxUploadSize" value="104857600" />
<property name="maxInMemorySize" value="2048" />
</bean>
好了,这下就可以正常使用了上传文件了,好TM开心,赶紧各种建文件夹,上传文件
此时第二个坑出现了(文件超过2M传上去就是一个blob文件,且只有几十k到1M多不等),第一反应这应该是个不完整的二进制文件,但为什么呢?F12打开浏览器,看了下发现上传文件时它一直在不停的发请求,原来是这个前端框架使用的大文件分段上传的技术,就是把一个文件切成很多小块,一直发请求,一点点的上传,而后台似乎并没有这样实现,所以造成了这种情况,相当于多大的文件,最后都只保存了最后一次上传的那一块,知道了原因,开始查elfinder的文档,看看他怎么说:果然还真有这样一个配置项:
他说默认是10M,这寻思也没有啊,我的文件超过2M就不行了,于是我就配置了一个这个,再在后面加了两个0,约等于1G了,再试,还是不行啊,超过2M就截断了,又开始查文档,以为是自己配置的姿势没对,弄了很久,不行,没办法,只能看他的elfinder.full.js了,看看是不是这其中有什么鬼,果然我发现了一个东西
这里默认为2M-8K的大小,和我们配置的大小中取一个,但使用的是Math.min,取得是其中小的一个,难怪我们的大了他就不用了,所能我们把他改成Math.max就可以使用我们配置的大小了,妈妈再也不用担心我给的容量不够了,注意这里查看的是elfinder.full.js(即原版),但我们引入的时候是引入的elfinder.mini.js(压缩版),所以要去mini.js中修改才有用,(因为mini版没有格式,不好找,这里告诉大家一个小技巧,可以Ctrl+F打开搜索框,搜索2097152,也就是上图里的数字,一下就找到了)(这里测试的时候因为本地tomcat给的空间不够,所报了一个OutMemoryError,内存溢出,不过不用担心,生产环境给的是16个G,随便他传)
还有一个问题就是上传时有一个选择目录,但好像支持得不太好,传不上去,也不知道怎么改,所以我索性就在elfinder.js中把这个给屏蔽了,过程如下:
浏览器中检查这个按钮,发现他的html代码为:
<div class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only elfinder-tabstop elfinder-focus"><span class="ui-button-text">
所以去elfinder.mini.js中搜索出来,在他之前加上一个判断,如果是选择目录,就返回一个空:
if(i=='selectFolder')return '<span></span>';
这里等于selectFolder是因为在elfinder.zh_CN.js 中可以找到 "选择目录"对应的英文就是“selectFolder”
到这里,基本配置就结束了,从使用上来说几乎是没有问题了。
剩下的就该考虑到部分需要优化的内容了:还记得我们最开始的时候说过,后台的jar包中给定了请求的url了,但只有一个,这很容易冲突,特别是项目大了过后,更大概率会出现了,所以我们就需要自己来定义url是最好的了,其次是权限的问题,特别是项目中涉及到一部分人能操作,一部分人只能查看、下载的问题,这个等下一篇再写了。。。(拖延一下……^-^)