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

前言

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

环境搭建

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

项目截图

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

109211-20190415194642054-346429409.png

109211-20190415194645812-801636717.png
109211-20190415194649326-1347955281.png

109211-20190415194653154-1900850449.png

109211-20190415194657214-2046186113.png

项目功能

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

项目配置

项目在第三方插件进行二次开发,基于 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>

小结

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

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

转载于:https://www.cnblogs.com/smallSevens/p/10712643.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Proxmox VE 7.3 Ceph超融合私有云建设案例是实现私有云建设的最佳方案之一。它是一个高度集成的平台,允许在单一硬件组件上集成计算、存储和网络部署。这意味着不再需要单独购买控制器和硬盘阵列,从而使架构更加轻量化、简单和易于管理。 该方案使用Ceph来管理储存,并为计算和网络提供服务。Ceph是一种可靠、可扩展的分布式存储系统,旨在提供比传统存储更好的性能和容错性。它使用分布式复制来确保数据的可用性,并通过数据分片和负载均衡来提高性能。 Proxmox VE 7.3 Ceph超融合私有云建设案例利用了Proxmox VE的虚拟化技术,可以轻松地在同一硬件上运行多个虚拟机,并可以快速扩展和回收资源。通过使用Proxmox VE中的集成管道和API,计算、存储和网络资源可以快速部署、配置和管理,使IT管理员可以更加专注于业务需求。 总的来说,Proxmox VE 7.3 Ceph超融合私有云建设案例提供了一种可靠、高效的私有云解决方案,将计算、存储和网络部署整合到同一硬件平台上,从而降低了成本、提高了效率、简化了管理。 ### 回答2: 随着数字化时代的到来,越来越多的企业需要构建私有云来保护自身的数据安全以及解决数据管理难题。而随着业界技术的不断进步,越来越多的企业开始采用超融合架构来构建自己的私有云。本文将介绍一种基于 Proxmox VE7.3 Ceph 超融合架构的私有云建设方案。 首先,需要了解的是什么是超融合架构。超融合是集计算、存储、网络为一体的一种分布式计算架构。超融合架构通常包含至少一个虚拟化管理节点、若干个存储节点以及若干个计算节点。在该架构中,存储节点和计算节点通常是相互独立的,但是在超融合架构中,这些节点被集成在一起,这样可以提高资源利用率和响应时间。相比传统的分布式计算架构,超融合架构更加具有可扩展性和可靠性。 本方案采用的是 Proxmox VE7.3 Ceph 超融合架构。Proxmox VE是基于Linux的虚拟化平台,可以支持多种虚拟化技术,如KVM和OpenVZ。而 Ceph 是一个开源的分布式存储系统,它具有高可靠性、高可扩展性和高性能等优点,非常适合超融合架构。 本方案的目标是构建一个具有高可用性和高可靠性的私有云。在该架构中,使用 Proxmox VE7.3 作为虚拟化管理节点,Ceph 作为存储节点。 首先,需要搭建虚拟化环境,安装和配置 Proxmox VE7.3。搭建虚拟化环境需要在一台硬件服务器上安装虚拟化软件,这样可以在该服务器上运行多个虚拟化操作系统。通过 Proxmox VE7.3 可以创建虚拟机,并通过 Web 界面方便的管理虚拟机。 接着,需要搭建 Ceph 存储集群。Ceph 基于 RADOS 对象存储系统,可以提供多个存储节点的高可用性,这样可以在存储节点故障时不会导致数据的丢失。在本方案中,需要安装和配置 Ceph 存储集群,创建块存储和文件存储。 最后,需要将虚拟化环境和 Ceph 存储集群集成在一起,创建具有高可用性和高可靠性的私有云。 总而言之,Proxmox VE7.3 Ceph 超融合架构是一种理想的构建高可用性和高可靠性的私有云的方案。它具有明显的优点,包括可扩展性、高可用性、高可靠性和高性能等。在实际应用中,需要根据实际情况进行调整,以达到最佳效果。 ### 回答3: Proxmox VE 7.3 Ceph超融合私有云建设方案是一种高效、安全的云解决方案,广泛应用于不同类型的企业,从小型公司到大型企业都适用。 在此方案下,企业可以完全控制其数据中心和计算资源,从而更好地掌控其业务。 此方案的一大特点在于其超融合架构,这意味着它集成了计算、存储和网络,可以更方便地管理和维护整个系统。企业也可以根据其需求来扩展或缩减其存储和计算服务。 Proxmox VE 7.3 Ceph超融合私有云建设方案依赖于三个关键组件。首先是Proxmox VE管理界面,它提供了一个统一的视图以便于管理集群节点、虚拟机和存储服务。其次是Ceph存储池,它托管了企业数据并提供高可靠性和复原性。最后是虚拟机,它允许企业为其应用程序提供虚拟化环境。 在此方案下,企业可以轻松地管理其存储池和虚机,从而实现资源优化。此外,此方案还提供了企业级的安全性和隔离性,包括访问控制和网络隔离等功能,保护数据不受安全性威胁。 总而言之,Proxmox VE 7.3 Ceph超融合私有云建设方案是扩展性和性价比非常高的方案,可以满足企业不断增长的需求,并为其提供高可靠性、安全性和可扩展性的存储和计算服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值