Bootstrap

基于springboot仿雀语的文档管理系统

项目介绍

本项目借鉴了雀语的一些UI设计,实现了文档在线管理的功能,知识库可以对不同分类的文档建立不同的库,知识库里面左边可以维护菜单菜单目录,右边实现在线预览。该项目可以防止用户下载和复制文档,只支持在线预览。

技术实现

文档上传的时候通过aspose把图片word和execel类型的文件转为pdf文件存储到nas,前端预览使用pdf.js加载预览pdf文档

项目预览

开发介绍

目录维护

左侧菜单点击加号可以维护目录

前端代码

<body class="white-bg">
    <div class="ibox-content">
        <form class="form-horizontal m-t" id="form1">
        <input id="id" name="id" type="hidden" />
        <input id="parentid" name="parentid" type="hidden" />
        <input id="deletemark" name="deletemark" type="hidden" />
        <input id="createdate" name="createdate" type="hidden" />
        <input id="createuserId" name="createuserId" type="hidden" />
        <input id="createusername" name="createusername" type="hidden" />
        <input id="modifydate" name="modifydate" type="hidden" />
        <input id="modifyuserid" name="modifyuserid" type="hidden" />
        <input id="modifyusername" name="modifyusername" type="hidden" />
        <div class="row">
            <div class="col-xs-12">
                <input type="text" id="name" class="form-control" placeholder="名称" />
            </div>
            <div class="col-xs-12">
                <textarea id="remark" class="form-control" placeholder="描述" style="width:100%;height:100px;"></textarea>
            </div>
            <div class="col-xs-12">
                <input type="text" id="sortcode" class="form-control" placeholder="序号" />
            </div>
            <div class="col-xs-12">
                <textarea id="keywords" class="form-control" placeholder="关键词" style="width:100%;height:100px;"></textarea>
            </div>
        </div>
        </form>
    </div>
</body>

后端代码

    @ApiOperation(value = "保存", notes = "")
    @PostMapping(value="/Save")
    public Result Save(@RequestBody String json) {
        DocmMenu model =  (DocmMenu) JSON.parseObject(json, DocmMenu.class);
        if(StrUtils.isBlank(model.getId())){
            model.setCreateuserid("admin");
            model.setDeletemark(new BigDecimal(0));
            model.setCreateusername("admin");
            model.setCreatedate(DateUtils.getNow());
            model.setId(UUID.randomUUID().toString());
            docmMenuService.add(model);
        }else {
            docmMenuService.update(model);
        }

        return Result.success(model,"成功!");
    }

文档维护

文档维护使用Dropzone实现前端文件上传,支持历史版本管理。

前端代码

<!DOCTYPE html>
<html>
<head>
    <title>文档管理</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" href="favicon.ico">
    <link href="../css/bootstrap.min.css" rel="stylesheet">
    <link href="../css/font-awesome.min.css" rel="stylesheet">
    <link href="../css/plugins/jsTree/style.min.css" rel="stylesheet">
    <link href="../css/plugins/bootstrap-table/bootstrap-table.min.css" rel="stylesheet">
    <link href="../css/plugins/dropzone/dropzone.css" rel="stylesheet" type="text/css" />
    <!-- 全局js -->
    <script src="../js/jquery.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
    <script src="../js/plugins/jsTree/jstree.min.js"></script>
    <script src="../js/plugins/bootstrap-table/bootstrap-table.min.js"></script>
    <script src="../js/plugins/layer/layer.min.js"></script>
    <script src="../js/plugins/dropzone/dropzone.js"></script>
    <script src="../js/bd-framework.js"></script>

</head>
<body class="white-bg">
<div>
    <table id="table" style="width:100%"></table>
    <div id="main-container" style="margin-top: 10px;">
        <form action="/" class="dropzone" enctype="multipart/form-data" id="my-dropzone"
              method="post">
        </form>
        <textarea id="remark" class="form-control" placeholder="上传备注" style="width:100%;height:100px;"></textarea>
        <div>
            <!--上传按钮,提供多张图片一次性上传的功能-->
            <button id="submit-all" class="btn btn-outline btn-default" type="submit" >上传</button>
        </div>
    </div>

</div>
<script>
    var $table = $('#table');
    $(function () {
        getFileList();
    })

    function getFileList() {
        $table.html("");
        $.get("/api/Attachment/getList?businessid="+GetQuery('businessid'), {}, function (result, resultState) {
         if (result.code == 200) {

                if (result.data.length > 0) {
                    $table.append('<tr style="text-align: center; vertical-align: middle; border-style:solid; border-width:1px; ">'
                                            + '<td style="border-style:solid; border-width:1px;"><div style="padding:10px;width:30px;">序号</div></td>'
                                            + '<td style="border-style:solid; border-width:1px;"><div style="padding:10px;width:100px;">文件名称</div></td>'
                                            + '<td style="border-style:solid; border-width:1px;"><div style="padding:10px;width:80px;">上传人员</div></td>'
                                            + '<td style="border-style:solid; border-width:1px;"><div style="padding:10px;width:100px;">上传日期</div></td>'
                                            + '<td style="border-style:solid; border-width:1px;"><div style="padding:10px;width:200px;">备注</div></td>'
                                            + '<td style="border-style:solid; border-width:1px;"><div style="padding:10px;width:50px;">操作</div></td>'
                                    + '</tr>'
                                       );
                    for (var i = 0; i < result.data.length; i++) {
                        if (result.data[i].EXTENSION != "pdf" || (result.data[i].TMP_BUSINESSID || '') =='') {
                            $table.append('<tr style="border-style:solid; border-width:1px;">'
                                          + '<td style="border-style:solid; border-width:1px;text-align:center;">' + (i + 1) + '</td>'
                                           + '<td style="border-style:solid; border-width:1px;">'
                                               + '<a onclick="Download(\'' + result.data[i].ID + '\')" style="float: left" href="javascript:void(0)"><u>' + result.data[i].NAME + '</u></a>'
                                           + '</td>'
                                           + '<td style="border-style:solid; border-width:1px;">' + result.data[i].CREATEUSERNAME + '</td>'
                                           + '<td style="border-style:solid; border-width:1px;">' + result.data[i].CREATETIME + '</td>'
                                           + '<td style="border-style:solid; border-width:1px;">' + (result.data[i].REMARK || '') + '</td>'
                                           + '<td style="border-style:solid; border-width:1px;">'
                                               + '<div style="position:relative;padding:10px;">'
                                                   + '<button type="button" onclick="FileDelete(\'' + result.data[i].ID + '\')" data-id="' + result.data[i].ID + '">'
                                                         + '删除'
                                                   + '</button>'
                                               + '</div>'
                                           + '</td>'
                                       + '</tr>'
                                       );
                        }

                    }
                }
            }
        })
    }
    function FileDelete(Id) {
        var index = parent.layer.confirm('是否删除?', {
            btn: ['是', '否'] //按钮
        }, function () {
            $.get("/api/Attachment/deleteByPDF", { id: Id }, function (result, resultState) {
                    if (result.code == 200) {
                    parent.layer.msg("删除成功!");
                    getFileList();
                } else {
                    parent.layer.msg(result.message);
                    getFileList();
                }
            }, "json");
            parent.layer.close(index);
        }, function () {
            parent.layer.close(index);
        });
    }
    function Download(Id) {
        window.open('/api/Attachment/downFile?id=' + Id);
    };
</script>
<script>
    var loadIndex = null;
    //Dropzone的初始化,myDropzone为form的id
    Dropzone.options.myDropzone = {
        params: {
            businessid: GetQuery('businessid'),
            filePath: 'DocM'
            // 您可以在这里添加其他参数
        },
        //指定上传的路径
        url: "/api/Attachment/uploadFilesToPDF",
        maxFiles: 1, // 用于限制此Dropzone将处理的最大文件数
        maxFilesize: 100, // MB
        acceptedFiles: ".doc,.docx,.pdf,.PDF,.jpg,.JPG,.gif,.GIF,.png,.PNG,.bmp,.BMP", // 上传的类型
        dictDefaultMessage:
            '<div style="text-align: center; vertical-align: middle;padding-top:38px;"><span>将文件拖拽到此处</span>  \
			<span>(或点击上传)</span></div>'
          ,
        dictResponseError: 'Error while uploading file!',
        dictFileTooBig: "最大100M",
        //添加上传取消和删除预览的链接,默认不添加
        addRemoveLinks: true,
        //关闭自动上传功能,默认会true会自动上传
        //也就是添加一张图片向服务器发送一次请求
        autoProcessQueue: false,
        //允许上传多个
        uploadMultiple: false,
        //记得修改web.config 限制上传文件大小的节
        parallelUploads: 100,
        init: function () {
            var submitButton = document.querySelector("#submit-all")
            myDropzone = this; // closure

            //为上传按钮添加点击事件
            submitButton.addEventListener("click", function () {
                Dropzone.options.myDropzone.params.remark = $("#remark").val();
                loadIndex = parent.layer.load();
                //手动上传所有文件
                myDropzone.processQueue();
            });

            //当添加图片后的事件,上传按钮恢复可用
            this.on("addedfile", function () {
                $("#submit-all").removeAttr("disabled");
            });
            //当上传完成后的事件,接受的数据为JSON格式
            this.on("complete", function (data) {
                parent.layer.close(loadIndex);
                if (this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0) {
                    var res = eval('(' + data.xhr.responseText + ')');
                    var msg;
                    if (res.code == 200) {
                        msg = "已成功上传!";
                        this.removeAllFiles();
                        getFileList()
                    }
                    else {
                        msg = "上传失败,失败的原因是:" + res.Message;
                    }
                    parent.layer.msg(msg);
                }
            });

            //删除文件的事件,当上传的文件为空时,使上传按钮不可用状态
            this.on("removedfile", function () {
                if (this.getAcceptedFiles().length === 0) {
                    $("#submit-all").attr("disabled", true);
                }
            });
        }
    };
</script>

</body>

后端代码

    @CrossOrigin
    @ApiOperation(value = "文件上传并且转为PDF", notes = "")
    @PostMapping("/uploadFileToPDF")
    public Result uploadFileToPDF(@RequestBody byte[] fileByte,
                             @RequestParam(value = "fileName",required = true) String fileName,
                             @RequestParam(value = "filePath",required = true) String filePath,
                             @RequestParam(value = "area",required = false) String area,
                             @RequestParam(value = "businessid",required = false) String businessid,
                             @RequestParam(value = "tmp_businessid",required = false) String tmp_businessid,
                             @RequestParam(value = "createUserId",required = false) String createUserId,
                             @RequestParam(value = "createUserName",required = false) String createUserName,
                             @RequestParam(value = "remark",required = false) String remark) {
        try {
            String uuid = UUID.randomUUID().toString();
            // 获取文件名
            String extension = getFileExtension(fileName);
            String newFileName = uuid + "." + extension;
            DocM_Attachment attachment = new DocM_Attachment();
            attachment.setBusinessid(businessid);

            attachment.setFilename(fileName);
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyMMdd");

            String uploadPath = filePath + FileConnect + LocalDate.now().format(fmt);
            attachment.setId(uuid);
            attachment.setCreateTime(DateUtils.getNow());
            attachment.setDirectory(uploadPath);
            attachment.setFilepath(uploadPath + FileConnect + newFileName);
            attachment.setFileSize(bytesToMegabytes((long)fileByte.length));
            attachment.setArea(area);
            attachment.setTmp_businessid(tmp_businessid);
            attachment.setExtension(extension);
            attachment.setCreateUserId(createUserId);
            attachment.setCreateUserName(createUserName);
            attachment.setRemark(remark);
            SmbFileUtils.save(fileByte,uploadPath,newFileName);

            InputStream inputStream = new ByteArrayInputStream(fileByte);
            OutputStream pdfStream = null;
            if(extension.equals("docx") || extension.equals("doc")){
                 pdfStream = doc2pdf(inputStream);
            }else if(extension.equals("png") || extension.equals("jpg") || extension.equals("gif")|| extension.equals("bmp")){
                 pdfStream = image2pdf(inputStream);
            }


            DocM_Attachment pdfAttachment = new DocM_Attachment();
            BeanUtils.copyProperties(attachment,pdfAttachment);
            pdfAttachment.setId(UUID.randomUUID().toString());
            String newPdfFileName = pdfAttachment.getId() + ".pdf";
            pdfAttachment.setFilepath(uploadPath + FileConnect + newPdfFileName);
            pdfAttachment.setArea("pdf");
            pdfAttachment.setTmp_businessid(attachment.getId());
            pdfAttachment.setFilename(fileName.split("\\.")[0] + ".pdf");
            pdfAttachment.setExtension("pdf");

            SmbFileUtils.save(toByteArray(pdfStream),uploadPath,newPdfFileName);

            inputStream.close();
            pdfStream.close();
            attachmentService.add(attachment);
            attachmentService.add(pdfAttachment);
            return Result.success(uuid,"成功!");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("文件上传失败");
        }
    }

知识库详情页面

左侧菜单使用JSTree.js插件,右侧文档预览使用pdf.js插件

前端代码

<!DOCTYPE html>
<html>
<head>
    <title>文档管理</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" href="favicon.ico">
    <link href="../css/bootstrap.min.css" rel="stylesheet">
    <link href="../css/font-awesome.min.css" rel="stylesheet">
    <link href="../css/plugins/jsTree/style.min.css" rel="stylesheet">
    <link href="../css/plugins/bootstrap-table/bootstrap-table.min.css" rel="stylesheet">
    <!-- 全局js -->
    <script src="../js/jquery.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
    <script src="../js/plugins/jsTree/jstree.min.js"></script>
    <script src="../js/plugins/bootstrap-table/bootstrap-table.min.js"></script>
    <script src="../js/plugins/layer/layer.min.js"></script>
    <script src="../js/bd-framework.js"></script>
</head>
<body class="white-bg">
    <style>
    .pdf
    {
       position:relative;    
    }
    .main_container
    {
      display:flex;
    }
    .left_container
    {
        width:320px;   
        border-right:1px solid #e7e9e8; 
        overflow:scroll;
    }
    .right_contaner
    {
        flex:1;
    }
    #tree
    {
     
    }
    .jstree-anchor {
      font-size: 14px !important;
     /* color:#262626 !important;*/
    }
    .jstree-default .jstree-node {
        margin-top: 3px; /* 调整节点顶部的间距 */
        margin-bottom: 3px; /* 调整节点底部的间距 */
    }
    .btn-power
    {
        display:none;    
    }
    </style>
    <div class="main_container">
         <div class="left_container">
             <div id="directoryExpand">
             <input type="text" id="Keywords" class="form-control" placeholder="关键词搜索" />
                 <div style="display:flex; justify-content: space-between;align-items: center;margin-bottom:8px;padding:4px;">
                    <div onclick="directoryExpand()" style="font-size: 14px;color:#262626;padding-left:25px;"><i class="fa fa-bars" style="margin-right:12px;"  ></i>目录</div>
                    <div>
                        <div style="position: absolute;margin-left:-90px;margin-top:-12px;" class="btn-power">
                         <button data-toggle="dropdown" class="btn btn-outline btn-default dropdown-toggle" type="button" aria-expanded="false">
                              <i class="glyphicon glyphicon-plus" aria-hidden="true"></i>     
                        </button>
                         <button  onclick="btn_deleteAll()" class="btn btn-outline btn-default" type="button" >
                              <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>     
                        </button>
                        <ul class="dropdown-menu pull-right">
                            <li>
                                <a href="javascript:;" onclick="btn_add()">新建分组</a>
                            </li>
                            <li>
                                <a href="javascript:;" onclick="btn_edit()">编辑分组</a>
                            </li>
                            <li>
                                <a href="javascript:;" onclick="btn_uploadFile()">上传文档</a>
                            </li>
                        </ul>
                        </div>
                    
                    </div>
                </div>
               
                <div id="tree"></div>
            </div>
            <div id="directoryNoExpand" style="display:none;">
                <div onclick="directoryNoExpand()" style="font-size: 14px;color:#262626;padding-left:12px;"><i class="fa fa-bars" ></i></div>
            </div>
         </div>
         <div class="right_contaner"  >
            <div class="pdf" >       
                <iframe  id="iframe1" width="100%" height="100%" src="" frameborder="0" ></iframe>
            </div>
         </div>
    </div>
    <script>
        var currentNode = null;
        var loadIndex = null;
        function directoryExpand() {
            $("#directoryExpand").hide();
            $(".left_container").css("width", "40px");
            $("#directoryNoExpand").show();   
        }
        function directoryNoExpand() {
            $("#directoryExpand").show();
            $(".left_container").css("width", "320px");
            $("#directoryNoExpand").hide();
        }
    
        $(function () {
            getPower();
           
            $(this).bind("contextmenu", function (e) {
                e.preventDefault();
            });
            $(".left_container").height($(window).height() - 7);
            $(".pdf").height($(window).height() - 7);
            document.getElementById('iframe1').onload = function () {
                parent.layer.close(loadIndex);
            }
            $("#Keywords").keydown(function (event) {
                initTree();
            });
        })
        var isManager = false;
        function getPower() {
            $.get("/api/DocManage/IsPowerMange", { id: GetQuery('Id') }, function (result, resultState) {
                if (result.code == 200) {
                    $(".btn-power").show();
                    isManager = true;
                }
                initTree();
            }, "json");
        }
        var $tree = $('#tree');
    
        function initTree() {
            if (!!GetQuery('Id')) {
                var postData = {}
                postData.id = GetQuery('Id');
                postData.keywords = $("#Keywords").val();
                $.get("/api/DocManage/GetTreeJson", postData, function (result, resultState) {
                    if (isManager) {
                        $tree
                        .on('activate_node.jstree', function (obj, e) {
                            var node = e.node;
                            if (node.id != undefined) {
                                currentNode = node;
                                loadPdf(node.id);
                            }
                        })
                        .jstree({
                            "multiple ": true,
                            'plugins': ["checkbox"],
                            'checkbox': {
                                'three_state': false,
                                'whole_node': false,
                                'tie_selection': false // 只有点击复选框才能勾选节点
                            },
                            'core': {
                                'data': result.data,
                                'check_callback': function (operation, node, node_parent, node_position, more) {
                                    // 允许所有操作,包括创建、重命名、删除、移动和复制节点
                                    return true;
                                }
                            }
                        })
                    } else {
                        $tree
                        .on('activate_node.jstree', function (obj, e) {
                            var node = e.node;
                            if (node.id != undefined) {
                                currentNode = node;
                                loadPdf(node.id);
                            }
                        })
                        .jstree({
                            "multiple ": true,
                            'core': {
                                'data': result.data
                            }
                        })
                    }
                }, "json");
            }
        }
        function loadPdf(businessid) {
            loadIndex = parent.layer.msg('文档加载中,请耐心等待!', { time: 1000 * 20 });
           
            $.get("/api/Attachment/getList?businessid="+businessid+"&area=pdf", {}, function (result, resultState) {
                if (result.code == 200) {
                    if (result.data.length > 0) {
                        for (var i = 0; i < result.data.length; i++) {
                            if (result.data[i].EXTENSION == "pdf") {
                                if (result.data[i].ID != currentNode.id) {
                                    $("#iframe1").attr("src", "../js/plugins/pdfjs-2.14.305-dist/web/DocManageViewer.html?file=" + "/api/Attachment/viewFile?id=" + result.data[i].ID);
                                }
                                break;
                            }
                        }
                    } else {
                        $("#iframe1").attr("src", "");
                        parent.layer.close(loadIndex);
                    }
                }
            }, "json");
        }
        function btn_add() {
            var viewData = {};
            if (currentNode) {
                viewData.parentid = currentNode.id;
            } else {
                viewData.parentid = GetQuery('Id')
            }
            var layerIndex = parent.layer.open({
                btn: ['确认'], //按钮
                yes: function (index, layero) {
                    var postData = parent.$("#layui-layer-iframe" + index)[0].contentWindow.GetWebControls("#form1");
                    $.ajax({
                        url: "/api/DocManage/Save",
                        type: "post",
                        contentType: 'application/json',
                        data: JSON.stringify(postData),
                        dataType: "json",
                        success: function (result) {
                            parent.layer.close(layerIndex);
                            // 在选中的节点下插入新节点
                            $tree.jstree('create_node', currentNode, { text: result.data.name, id: result.data.id, icon: "no-icon" }, 'last', function (newNode) {
                                //console.log('New node created with ID:', newNode.id);
                            });
                        }
                    });
                },
                type: 2,
                title: '新增',
                area: ['350px', '550px'],
                shadeClose: true, //开启遮罩关闭
                content: '/docManage/menuEdit.html',
                success: function (layero, index) {
                    parent.$("#layui-layer-iframe" + index)[0].contentWindow.SetWebControls(viewData);
                }
            });
        }
    
        function btn_edit() {
            var viewData = {};
            if (currentNode) {
                viewData.parentid = currentNode.id;
            } else {
                parent.layer.msg("请选择一个分组")
                return;
            }
            var layerIndex = parent.layer.open({
                btn: ['确认', '删除'], //按钮
                yes: function (index, layero) {
                    var postData = parent.$("#layui-layer-iframe" + index)[0].contentWindow.GetWebControls("#form1");
                    $.ajax({
                        url: "/api/DocManage/Save",
                        type: "post",
                        contentType: 'application/json',
                        data: JSON.stringify(postData),
                        dataType: "json",
                        success: function (result) {
                            parent.layer.close(layerIndex);
                            $tree.jstree('rename_node', currentNode, result.data.name);
                        }
                    });
                }, btn2: function (index, layero) {
                    var index = parent.layer.confirm('是否删除?', {
                        btn: ['是', '否'] //按钮
                    }, function () {
                        if (currentNode) {
                            var postData = {};
                            postData.id = currentNode.id;
                            $.get("/api/DocManage/Delete", postData, function (result, resultState) {
                                if (result.code == 200) {
                                    parent.layer.close(layerIndex);
                                    $tree.jstree('delete_node', currentNode);
                                }
                            }, "json");
                        }
                        parent.layer.close(index);
                    }, function () {
                        parent.layer.close(index);
                    });
                },
                type: 2,
                title: '编辑',
                area: ['350px', '550px'],
                shadeClose: true, //开启遮罩关闭
                content: '/docManage/menuEdit.html',
                success: function (layero, index) {
                    $.get("/api/DocManage/GetDetail", { id: currentNode.id }, function (result, resultState) {
                        parent.$("#layui-layer-iframe" + index)[0].contentWindow.SetWebControls(result.data);
                    }, "json");
    
                }
            });
        }
        function btn_deleteAll() {
            var index = parent.layer.confirm('是否删除?', {
                btn: ['是', '否'] //按钮
            }, function () {
                var postData = {};
                postData.ids = getTreeSelectedData().join(',');
                $.get("/api/DocManage/DeleteAll", postData, function (result, resultState) {
                    parent.layer.close(index);
                    $tree.jstree('delete_node', getTreeSelectedData());
                }, "json");
            }, function () {
                parent.layer.close(index);
            });
        }
        function btn_uploadFile() {
            var viewData = {};
            if (currentNode) {
                viewData.parentid = currentNode.id;
            } else {
                parent.layer.msg("请选择一个分组")
                return;
            }
            parent.layer.open({
                type: 2,
                title: '上传文档',
                area: ['850px', '750px'],
                shadeClose: true, //开启遮罩关闭
                content: '/docManage/uploadFileViewToPDF.html?businessid=' + currentNode.id,
                success: function (layero, index) {
                }
            });
        }
        function getTreeSelectedData() {
            var nodes = $tree.jstree("get_checked"); //使用get_checked方法
            return nodes;
        }
    </script>
    
</body>

文件转为pdf

使用aspose把文件转为pdf

    public OutputStream doc2pdf(InputStream inputStream) throws Exception {
        // 验证License 若不验证则转化出的pdf文档会有水印产生
        if (!getLicense()) {
            return null;
        }
        try {
            OutputStream outputStream =  new ByteArrayOutputStream();
            Document doc = new Document(inputStream);
            // 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            doc.save(outputStream, SaveFormat.PDF);
            return  outputStream;
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("word转pdf失败");
        }
    }

访问nas

使用jcifs-ng访问nas

导入包

<!-- samba共享文件夹-->
<dependency>
    <groupId>eu.agno3.jcifs</groupId>
    <artifactId>jcifs-ng</artifactId>
    <version>2.1.3</version>
</dependency>

工具栏

public class SmbFileUtils {
    static String ip = "";
    static String domain = "";
    static String userName = "";
    static String password = "";

    static void SmbFileUtils(){

    }
    //根据账号密码登录
    private static CIFSContext withNTLMCredentials(CIFSContext ctx) {
        return ctx.withCredentials(new NtlmPasswordAuthenticator(domain,
                userName, password));
    }

    //保存文件
    public static String save(byte[] byteArr, String url,String fileName) throws IOException {
        InputStream in = new ByteArrayInputStream(byteArr);
        String status = "";
        try {
            CIFSContext context = withNTLMCredentials(SingletonContext.getInstance());
            SmbFileWriter.createDirectory("smb://" + domain  +"/" + url, context);
            boolean result = SmbFileWriter.writeSmbFile(in, "smb://" + domain  +"/" + url +"/" + fileName, context);
            status = "success";
        } catch (Exception e) {
            e.printStackTrace();
            status = "error";
        } finally {
            in.close();
            return status;
        }
    }

    //获取文件
    public static  InputStream getFile(String filePath) throws IOException {
        String url = "smb://" + domain + "/" + filePath;

        try {
            CIFSContext context = withNTLMCredentials(SingletonContext.getInstance());
            SmbFileReader reader = new SmbFileReader();
            byte[] byteArr = reader.readSmbFile(url, context);
            InputStream input = new ByteArrayInputStream(byteArr);
            return  input;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    //删除文件
    public static String delete(String filePath) throws IOException {
        String status = "";
        String url = "smb://" + domain + "/" + filePath;

        try {
            CIFSContext context = withNTLMCredentials(SingletonContext.getInstance());
            SmbFile file = new SmbFile(url, context);
            if (file.exists()) {
                file.delete();
                status = "success";
            }
        } catch (Exception e) {
            e.printStackTrace();
            status = "error";
        }
        return status;
    }
    //获取文件列表
    public static  List<HashMap> getPathList(String path) throws IOException {
        String url = "smb://" + domain + "/" + path;
        List<HashMap> filesList = new ArrayList<>();
        CIFSContext context = withNTLMCredentials(SingletonContext.getInstance());
        try {
            SmbFile smbFile = new SmbFile(url, context);
            SmbFile[] files = smbFile.listFiles();
            for (SmbFile file : files) {
                HashMap fileMap =new HashMap();
                fileMap.put("fileName",file.getName());
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 定义日期格式
                fileMap.put("date",sdf.format(new Date(file.getDate())));
                fileMap.put("size", String.format("%.2f", (file.length()/1024.0)/1024.0)+"MB");
                fileMap.put("fileType",file.isDirectory()?"文件夹":"文件");
                filesList.add(fileMap);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return filesList;
    }

    static class SmbFileReader {
        public byte[] readSmbFile(String path, CIFSContext context) throws IOException {
            try  {
                SmbFile smbFile = new SmbFile(path, context);
                long fileSize = smbFile.length();
                if (fileSize > Integer.MAX_VALUE) {
                    System.out.println("file too big...");
                    return null;
                }
                InputStream fi = smbFile.getInputStream();
                byte[] buffer = new byte[(int) fileSize];
                int offset = 0;
                int numRead = 0;
                while (offset < buffer.length
                        && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
                    offset += numRead;
                }
                // 确保所有数据均被读取
                if (offset != buffer.length) {
                    throw new IOException("Could not completely read file "
                            + smbFile.getName());
                }
                fi.close();
                return buffer;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    static class SmbFileWriter {
        static boolean writeSmbFile(String source, String target, CIFSContext context) throws IOException {
            if (StrUtils.isEmpty(source) || StrUtils.isEmpty(target)) {
                return false;
            }
            return writeSmbFile(Files.newInputStream(Paths.get(source)),
                    target, context);
        }

        static boolean writeSmbFile(InputStream in, String target, CIFSContext context) throws IOException {
            if (Objects.nonNull(in) && StrUtils.isNotEmpty(target)) {
                try (SmbFile file = new SmbFile(target, context)) {
                    try (SmbFile parent = new SmbFile(file.getParent(), context)) {
                        if (!parent.exists()) {
                            createDirectory(file.getParent(), context);
                        }
                        if (!file.exists()) {
                            file.createNewFile();
                        }
                    }
                    try (OutputStream os = file.getOutputStream()) {
                        byte[] bytes = new byte[1024];
                        while (in.read(bytes) != -1) {
                            os.write(bytes);
                        }
                        return true;
                    }
                }finally {
                    in.close();
                }
            }
            return false;
        }

        static SmbFile createDirectory(String targetDir, CIFSContext context) throws MalformedURLException,
                CIFSException, MalformedURLException {
            try (SmbFile dir = new SmbFile(targetDir, context)) {
                if (!dir.exists()) {
                    dir.mkdir();
                }
                return dir;
            }
        }
    }
}
;