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

news/2024/7/5 14:46:26 标签: java, 前端, javascript

前言

最近在做工作流的事情,正好有个需求,要添加一个附件上传的功能,曾找过不少上传插件,都不是特别满意。无意中发现一个很好用的开源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:

java">@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 控制层实现:

java">@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);
        }
    }
    //省略部分代码
}

最后,前端页面引入:

javascript"><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


http://www.niftyadmin.cn/n/1413535.html

相关文章

MySQL TOO BAD row's Range Lock Compare with PostgreSQL and Oracle

MySQL的InnoDB引擎&#xff0c;当UPDATE一个范围的数据时&#xff0c;会锁住比预期更多的ROW&#xff0c;而Oracle和PostgreSQL没有这种现象.来自《High Performance MySQL》一书。测试版本:MySQL 5.5.10PostgreSQL 9.0.2Oracle 10.2.0.4举例如下:1. MySQL (有索引的情况)Sessi…

数论——找新朋友 (欧拉函数)

新年快到了&#xff0c;“猪头帮协会”准备搞一个聚会&#xff0c;已经知道现有会员N人&#xff0c;把会员从1到N编号&#xff0c;其中会长的号码是N号&#xff0c;凡是和会长是老朋友的&#xff0c;那么该会员的号码肯定和N有大于1的公约数&#xff0c;否则都是新朋友&#xf…

Windows server 2003 QQ宠物猪伴侣出错解决办法

运行pigmate后&#xff0c;桌面什么都没有&#xff0c;右下角系统托盘也没有图标&#xff0c;在任务管理器里面倒是可以看到“猪猪伴侣”的条目&#xff0c;运行QQ宠物猪&#xff0c;也不见被伴侣托管 系统平台&#xff1a;enterprise server 2003 sp2 别人的解决方案&#xff…

vue从入门到进阶:渲染函数 JSX(八)

文章目录节点、树以及虚拟 DOMcreateElement 参数 深入 data 对象完整示例约束使用 JavaScript 代替模板功能 v-if 和 v-forv-model事件 & 按键修饰符插槽JSX函数式组件 slots() 和 children 对比Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。然而在一些场景中…

Akka简单性能分析

因为最近工作的关系&#xff0c;要把异步任务从应用服务器中拆分到专门的异步处理服务器中。 方案一 是采用MQ的方式将任务消息发出&#xff0c;在服务端进行处理&#xff0c;这种方案是采用MQ作为中间的媒介&#xff0c;在服务端采用线程池异步处理任务&#xff0c;处理完成之…

数论——欧拉函数及欧拉打表

欧拉函数的功能&#xff1a;用于求小于n的与n互质数的个数 欧拉函数的作用&#xff1a;用于求小于n的与n互质数的个数 欧拉函数的公式&#xff1a; φ(n)n*(1-1/p1)(1-1/p2)(1-1/p3)*(1-1/p4)……(1-1/pn), 其中p1, p2……pn为n的所有质因数&#xff0c;n是不为0的整数。φ(1)…

这个控件该怎么做呢?

组件名称: THZDBEdit 功能: 结合TDBEdit 的数据感应功能, 1.支持纯数字/日期时间格式hh:nn /文字的输入 EditMask2.支持三种显示效果 DisplayStyle传统效果 下划线: 平板边框: 3.要求失去光标的时候显示效果为以上效果, 如果得到光标 则,根据设置显示 ComboBox 下拉选择…

小波变换后逆小波变换重构

小波图像分解与重构 正常应该无损重构的&#xff0c;但是在处理中介入了阈值&#xff0c;再重构会有少许误差。 【转载自】 HAAR小波变换 - 豆丁网 https://www.docin.com/p-663309428.html转载于:https://www.cnblogs.com/wxl845235800/p/10720649.html