SpringBoot开发案例之打造私有云网盘

SpringBoot开发案例之打造私有云网盘

 

前言

最近在做工作流的事情,正好有个需求,要添加一个附件上传的功能,曾找过不少上传插件,都不是特别满意。无意中发现一个很好用的开源web文件管理器插件 elfinder,功能比较完善,社区也很活跃,还方便二次开发。

环境搭建

软件地址SpringBoothttps://spring.io/projects/spring-boot/elFinderhttps://studio-42.github.io/elFinder/

项目截图

周末抽时间做了一个简单的案例,希望对大家有所帮助,下面是简单的项目截图。

SpringBoot开发案例之打造私有云网盘

 

SpringBoot开发案例之打造私有云网盘

 

SpringBoot开发案例之打造私有云网盘

 

SpringBoot开发案例之打造私有云网盘

 

SpringBoot开发案例之打造私有云网盘

 

项目功能

在线新建目录、文件、附件上传、下载、预览、在线打包,图片在线裁剪、编辑,实现列表试图、图标视图等等一些列功能。

项目配置

项目在第三方插件进行二次开发,基于 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+'" style="width:100%; height:100%;"/>').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>

小结

总体来说个人使用还是非常不错的,当然对于一些成熟的网盘系统还是有一些差距。SpringBoot开发案例之打造私有云网盘

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页