前言
最近在做工作流的事情,正好有个需求,要添加一个附件上传的功能,曾找过不少上传插件,都不是特别满意。无意中发现一个很好用的开源web文件管理器插件 elfinder,功能比较完善,社区也很活跃,还方便二次开发。
环境搭建
软件地址springboothttps://spring.io/projects/spring-boot/elfinderhttps://studio-42.github.io/elfinder/项目截图
周末抽时间做了一个简单的案例,希望对大家有所帮助,下面是简单的项目截图。
项目功能
在线新建目录、文件、附件上传、下载、预览、在线打包,图片在线裁剪、编辑,实现列表试图、图标视图等等一些列功能。
项目配置
项目在第三方插件进行二次开发,基于 springboot 注解配置实现。
application.properties 配置:# 执行类,内部调用,实现前端相关功能
file-manager.command=com.itstyle.cloud.common.elfinder.command
file-manager.thumbnail.width=80
file-manager.volumes[0].node=
file-manager.volumes[0].source=filesystem
file-manager.volumes[0].alias=file
# 文件存放目录,可以自定义
file-manager.volumes[0].path=d:/cloudfile
file-manager.volumes[0]._default=true
file-manager.volumes[0].locale=
file-manager.volumes[0].constraint.locked=false
file-manager.volumes[0].constraint.readable=true
file-manager.volumes[0].constraint.writable=true elfinderconfiguration 读取配置:@component
@configurationproperties(prefix="file-manager") //接收application.properties中的file-manager下面的属性
public class elfinderconfiguration {
private thumbnail thumbnail;
private string command;
private list<node> volumes;
private long maxuploadsize = -1l;
//省略部分代码
} elfinderstoragefactory 初始化 基础bean:@configuration
public class elfinderconfig {
@autowired
private elfinderconfiguration elfinderconfiguration;
@bean(name = "commandfactory")
public commandfactory getcommandfactory() {
commandfactory commandfactory = new commandfactory();
commandfactory.setclassnamepattern(elfinderconfiguration.getcommand()+".%scommand");
return commandfactory;
}
@bean(name = "elfinderstoragefactory")
public elfinderstoragefactory getelfinderstoragefactory() {
defaultelfinderstoragefactory elfinderstoragefactory = new defaultelfinderstoragefactory();
elfinderstoragefactory.setelfinderstorage(getelfinderstorage());
return elfinderstoragefactory;
}
@bean(name = "elfinderstorage")
public elfinderstorage getelfinderstorage() {
defaultelfinderstorage defaultelfinderstorage = new defaultelfinderstorage();
// creates thumbnail
defaultthumbnailwidth defaultthumbnailwidth = new defaultthumbnailwidth();
defaultthumbnailwidth.setthumbnailwidth(elfinderconfiguration.getthumbnail().getwidth().intvalue());
// creates volumes, volumeids, volumelocale and volumesecurities
character defaultvolumeid = 'a';
list<node> elfinderconfigurationvolumes = elfinderconfiguration.getvolumes();
list<volume> elfindervolumes = new arraylist<>(elfinderconfigurationvolumes.size());
map<volume, string> elfindervolumeids = new hashmap<>(elfinderconfigurationvolumes.size());
map<volume, locale> elfindervolumelocales = new hashmap<>(elfinderconfigurationvolumes.size());
list<volumesecurity> elfindervolumesecurities = new arraylist<>();
// creates volumes
for (node elfinderconfigurationvolume : elfinderconfigurationvolumes) {
final string alias = elfinderconfigurationvolume.getalias();
final string path = elfinderconfigurationvolume.getpath();
final string source = elfinderconfigurationvolume.getsource();
final string locale = elfinderconfigurationvolume.getlocale();
final boolean islocked = elfinderconfigurationvolume.getconstraint().islocked();
final boolean isreadable = elfinderconfigurationvolume.getconstraint().isreadable();
final boolean iswritable = elfinderconfigurationvolume.getconstraint().iswritable();
// creates new volume
volume volume = volumesources.of(source).newinstance(alias, path);
elfindervolumes.add(volume);
elfindervolumeids.put(volume, character.tostring(defaultvolumeid));
elfindervolumelocales.put(volume, localeutils.tolocale(locale));
// creates security constraint
securityconstraint securityconstraint = new securityconstraint();
securityconstraint.setlocked(islocked);
securityconstraint.setreadable(isreadable);
securityconstraint.setwritable(iswritable);
// creates volume pattern and volume security
final string volumepattern = character.tostring(defaultvolumeid) + elfinderconstants.elfinder_volume_sercurity_regex;
elfindervolumesecurities.add(new defaultvolumesecurity(volumepattern, securityconstraint));
// prepare next volumeid character
defaultvolumeid++;
}
defaultelfinderstorage.setthumbnailwidth(defaultthumbnailwidth);
defaultelfinderstorage.setvolumes(elfindervolumes);
defaultelfinderstorage.setvolumeids(elfindervolumeids);
defaultelfinderstorage.setvolumelocales(elfindervolumelocales);
defaultelfinderstorage.setvolumesecurities(elfindervolumesecurities);
return defaultelfinderstorage;
}
} clouddiskcontroller 控制层实现:@controller
@requestmapping("elfinder/connector")
public class clouddiskcontroller {
private static final logger logger = loggerfactory.getlogger(clouddiskcontroller.class);
public static final string open_stream = "openstream";
public static final string get_parameter = "getparameter";
@resource(name = "commandfactory")
private elfindercommandfactory elfindercommandfactory;
@resource(name = "elfinderstoragefactory")
private elfinderstoragefactory elfinderstoragefactory;
@requestmapping
public void connector(httpservletrequest request, final httpservletresponse response) throws ioexception {
try {
response.setcharacterencoding("utf-8");
request = processmultipartcontent(request);
} catch (exception e) {
throw new ioexception(e.getmessage());
}
string cmd = request.getparameter(elfinderconstants.elfinder_parameter_command);
elfindercommand elfindercommand = elfindercommandfactory.get(cmd);
try {
final httpservletrequest protectedrequest = request;
elfindercommand.execute(new elfindercontext() {
@override
public elfinderstoragefactory getvolumesourcefactory() {
return elfinderstoragefactory;
}
@override
public httpservletrequest getrequest() {
return protectedrequest;
}
@override
public httpservletresponse getresponse() {
return response;
}
});
} catch (exception e) {
logger.error("unknown error", e);
}
}
//省略部分代码
} 最后,前端页面引入:<div id="elfinder"></div>
<script type="text/javascript" charset="utf-8">
window.onload = function() {
elfinder.prototype.loadcss('/elfinder/jquery-ui-1.12.1.custom/jquery-ui.css');
$('#elfinder').elfinder({
url : '/elfinder/connector',
lang: 'zh_cn',
height : window.innerheight-20,
commandsoptions: {
edit: {
editors : [
{
info:{
name:'编辑',
urlascontent: false
},
// ace editor
// `mimes` is not set for support everything kind of text file
load : function(textarea) {
var self = this,
dfrd = $.deferred(),
cdn = './elfinder/ace/',
init = function() {
if (typeof ace === 'undefined') {
console.log(cdn);
this.fm.loadscript([
cdn+'/ace.js',
cdn+'/ext-modelist.js',
cdn+'/ext-settings_menu.js',
cdn+'/ext-language_tools.js'
], start);
} else {
start();
}
},
start = function() {
var editor, editorbase, mode,
ta = $(textarea),
tabase = ta.parent(),
dialog = tabase.parent(),
id = textarea.id + '_ace',
ext = self.file.name.replace(/^.+\.([^.]+)|(.+)$/, '$1$2').tolowercase(),
// mime/mode map
mimemode = {
'text/x-php' : 'php',
'application/x-php' : 'php',
'text/html' : 'html',
'application/xhtml+xml' : 'html',
'text/javascript' : 'javascript',
'application/javascript' : 'javascript',
'text/css' : 'css',
'text/x-c' : 'c_cpp',
'text/x-csrc' : 'c_cpp',
'text/x-chdr' : 'c_cpp',
'text/x-c++' : 'c_cpp',
'text/x-c++src' : 'c_cpp',
'text/x-c++hdr' : 'c_cpp',
'text/x-shellscript' : 'sh',
'application/x-csh' : 'sh',
'text/x-python' : 'python',
'text/x-java' : 'java',
'text/x-java-source' : 'java',
'text/x-ruby' : 'ruby',
'text/x-perl' : 'perl',
'application/x-perl' : 'perl',
'text/x-sql' : 'sql',
'text/xml' : 'xml',
'application/docbook+xml' : 'xml',
'application/xml' : 'xml'
};
// set basepath of ace
ace.config.set('basepath', cdn);
// set base height
tabase.height(tabase.height());
// detect mode
mode = ace.require('ace/ext/modelist').getmodeforpath('/' + self.file.name).name;
if (mode === 'text') {
if (mimemode[self.file.mime]) {
mode = mimemode[self.file.mime];
}
}
// show mime:mode in title bar
tabase.prev().children('.elfinder-dialog-title').append(' (' + self.file.mime + ' : ' + mode.split(/[\/\\]/).pop() + ')');
// textarea button and setting button
$('<div class="ui-dialog-buttonset"/>').css('float', 'left')
.append(
$('<button>文本框</button>')
.button()
.on('click', function(){
if (ta.data('ace')) {
ta.removedata('ace');
editorbase.hide();
ta.val(editor.session.getvalue()).show().focus();
$(this).text('编辑器');
} else {
ta.data('ace', true);
editorbase.show();
editor.setvalue(ta.hide().val(), -1);
editor.focus();
$(this).text('文本框');
}
})
)
.append(
$('<button>ace editor setting</button>')
.button({
icons: {
primary: 'ui-icon-gear',
secondary: 'ui-icon-triangle-1-e'
},
text: false
})
.on('click', function(){
editor.showsettingsmenu();
})
)
.prependto(tabase.next());
// base node of ace editor
editorbase = $('<div id="'+id+'"/>').text(ta.val()).insertbefore(ta.hide());
// ace editor configure
ta.data('ace', true);
editor = ace.edit(id);
ace.require('ace/ext/language_tools');
ace.require('ace/ext/settings_menu').init(editor);
editor.$blockscrolling = infinity;
editor.setoptions({
theme: 'ace/theme/dawn',
mode: 'ace/mode/' + mode,
fontsize: '14px',
wrap: true,
enablebasicautocompletion: true,
enablesnippets: true,
enableliveautocompletion: true
});
editor.commands.addcommand({
name : "savefile",
bindkey: {
win : 'ctrl-s',
mac : 'command-s'
},
exec: function(editor) {
self.dosave();
}
});
editor.commands.addcommand({
name : "closeeditor",
bindkey: {
win : 'ctrl-w|ctrl-q',
mac : 'command-w|command-q'
},
exec: function(editor) {
self.docancel();
}
});
editor.resize();
dfrd.resolve(editor);
};
// init & start
init();
return dfrd;
},
close : function(textarea, instance) {
if (instance) {
instance.destroy();
$(textarea).show();
}
},
save : function(textarea, instance) {
instance && $(textarea).data('ace') && (textarea.value = instance.session.getvalue());
},
focus : function(textarea, instance) {
instance && $(textarea).data('ace') && instance.focus();
},
resize : function(textarea, instance, e, data) {
instance && instance.resize();
}
}
]
},
quicklook : {
// to enable preview with google docs viewer
googledocsmimes : ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
}
}
});
};
</script> 小结
总体来说个人使用还是非常不错的,当然对于一些成熟的网盘系统还是有一些差距。
源码:https://gitee.com/52itstyle/spring-boot-clouddisk
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持CodeAE代码之家。
原文链接:https://blog.52itstyle.vip/archives/3897/
|