评论

收藏

[Java] SpringBoot开发案例之打造私有云网盘的实现

编程语言 编程语言 发布于:2021-08-17 11:53 | 阅读数:295 | 评论:0

前言
最近在做工作流的事情,正好有个需求,要添加一个附件上传的功能,曾找过不少上传插件,都不是特别满意。无意中发现一个很好用的开源web文件管理器插件 elfinder,功能比较完善,社区也很活跃,还方便二次开发。
环境搭建
软件地址springboothttps://spring.io/projects/spring-boot/elfinderhttps://studio-42.github.io/elfinder/项目截图
周末抽时间做了一个简单的案例,希望对大家有所帮助,下面是简单的项目截图。
DSC0000.png

DSC0001.jpg

DSC0002.jpg

DSC0003.jpg

DSC0004.jpg

项目功能
在线新建目录、文件、附件上传、下载、预览、在线打包,图片在线裁剪、编辑,实现列表试图、图标视图等等一些列功能。
项目配置
项目在第三方插件进行二次开发,基于 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/

关注下面的标签,发现更多相似文章