前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用SpringBoot纯手工打造私人云网盘!!!

用SpringBoot纯手工打造私人云网盘!!!

作者头像
用户5224393
发布2019-07-10 11:21:39
1.9K0
发布2019-07-10 11:21:39
举报
文章被收录于专栏:Java研发军团Java研发军团

前言

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

环境搭建

软件

地址

SpringBoot

https://spring.io/projects/spring-boot/

elFinder

https://studio-42.github.io/elFinder/

项目截图

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

项目功能

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

项目配置

项目基于 SpringBoot 注解配置实现,在第三方插件进行二次开发。

application.properties 配置:

# 执行类,内部调用,实现前端相关功能file-manager.command=com.itstyle.cloud.common.elfinder.commandfile-manager.thumbnail.width=80file-manager.volumes[0].Node=file-manager.volumes[0].source=fileSystemfile-manager.volumes[0].alias=file# 文件存放目录,可以自定义file-manager.volumes[0].path=D:/cloudFilefile-manager.volumes[0]._default=truefile-manager.volumes[0].locale=file-manager.volumes[0].constraint.locked=falsefile-manager.volumes[0].constraint.readable=truefile-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:

@Configurationpublic 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>

小结

总体来说个人使用还是非常不错的,当然对于一些成熟的网盘系统还是有一些差距。

源码:

https://gitee.com/52itstyle/spring-boot-CloudDisk

在线演示地址:https://cloud.52itstyle.vip

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java研发军团 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 环境搭建
  • 项目截图
  • 项目功能
  • 项目配置
  • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档