Java 轮播功能实现 (图片预览+文件上传+数据加密)

轮播功能实现

前端为 LayUI 框架,所涉及到的知识点包括 图片预览,文件上传,blob数据处理 ,LayUI数据表格加载时自动选中 和数据加密(DEC)。

1.轮播效果的实现
html代码,定义轮播容器

<div class="layui-carousel" id="rotation">
    <div carousel-item id="rotationItem" style="height: 350px"></div>
</div>

JS代码
jQuery处理blob数据的方法为 function getBinary()

/**
 * Created by suzhaoxi on 2021/12/13.
 */
layui.use(['table','jquery','HussarAjax','carousel','layer','Hussar','element'], function() {
    var element = layui.element;
    var table = layui.table;
    var Hussar = layui.Hussar;
    var $ = layui.jquery;
    var layer = layui.layer;
    const ctxPath = Hussar.ctxPath;
    var $ax = layui.HussarAjax;
    var carousel = layui.carousel;


    // 公用方法,jQuery处理图片流,用js写
    function getBinary(url, args, id ) {
        var xmlhttp = new XMLHttpRequest();
        var data = eval(args);
        var i = 0;
        for (var key in data) {
            if (i++ === 0) {
                url += '?' + key + "=" + data[key];
            } else {
                url += '&' + key + "=" + data[key];
            }
        }
        xmlhttp.open("GET", url, true);
        xmlhttp.responseType = "blob";
        xmlhttp.onload = function () {
            var img = $('#'+id);
            window.URL.revokeObjectURL(img.src);
            $('#'+id).attr('src', window.URL.createObjectURL(this.response));
        };
        xmlhttp.send();
    }


	// 生成轮播的方法
    function rotation() {
        $.ajax({
        	// 从数据库中得到一些基本参数
            url: ctxPath + "/homeRotation/getRotationListsInHome" ,
            type: 'POST',
            dataType: 'JSON',
            data: {},
            success: function (result) {
                var data = result.data;
                console.log(result)
                if (result.count == 0){  // 如果没有图片,就放一张默认的图片
                    $("#rotationItem").append('<div calss><a target="_blank"> <img src=/static/img01/蒙版组%203.png style="auto;height: 100%;width: 100%"></a> </divcalss>');
                }else {
                    for (let i = 0; i < result.count; i++) {
                        var pic = data[i].pic;
                        var url = data[i].url;
                        var id = data[i].id;
                        var title = data[i].title;
                        // 对轮播的 div 进行一些设置,包括 id , 标题 , href 和 图片(该处只得到一个图片的路径,需进一步处理) 
                        $("#rotationItem").append('<div calss><a href="' + ctxPath + url + '" target="_blank"> <img id="' + id + '" title=" '+title+' " style="auto;height: 100%;width: 100%"></a> </divcalss>');
                        function readImg() { 
                        	// 处理图片(根据图片路径pic找到图片,转化成二进制流数据并展示)
                        	// homeRotation/IoReadImage,读取本地文件的方法,下文会写
                            getBinary("/homeRotation/IoReadImage",{'src': pic},id);
                        }
                        readImg();
                    }
                }
                // 重新加载轮播(二者缺一不可)
                var ins = carousel.render({  
                    elem: '#rotation' // 绑定容器ID
                    ,interval: 4500  // 设置切换时间
                    ,height: '350px'  // 设置容器高度
                    ,width: '100%' //设置容器宽度
                    ,arrow: 'always' //始终显示箭头;
                });
                ins.reload({
                    elem: '#rotation' // 绑定容器ID
                    ,interval: 4500   // 设置切换时间
                    ,height: '350px'  // 设置容器高度
                    ,arrow: 'always'  // 始终显示箭头
                    ,anim: 'always'   // 换动画方式,可选fade,default,updown
                });
            }
        });
    }
    rotation();

	// 这里定义一个轮播容器
    carousel.render({
        elem: '#rotation' // 绑定容器ID
        ,interval: 4500   // 设置切换时间
        ,height: '350px'  // 设置容器高度
        ,width: '100%' //设置容器宽度
        ,arrow: 'always' //始终显示箭头
    });


});

所以轮播实现至少要包含两个基本元素,图片上传和链接的跳转。上传图片时,就必然牵涉到预览。

2.轮播后台配置页
因为一条轮播,不仅是图片上传,还包括绑定公示公告等( 链接是开发的项目中的一些公示公告,均为 get 请求跳转),所以,一条轮播主要的两个按钮为 图片上传 和 确定保存( 或修改)。
html代码

<form class="layui-form">
    <div class="tec-empty"></div>
    <div class="theRealContent">
	<!-- 轮播图片展示-->
	<div class="layui-form-item" id="previewImg">
	    <div class="layui-upload-list">
	        <img class="layui-upload-img" id="demo1" src="">
	        <p id="demoText"></p><br>
	        <span style="color:  #27b7b0">-- 效果图预览 -- 推荐比例 (4:1) --</span>
	    </div>
	</div>
	
	<div class="layui-form-item">
	    <div class="layui-col-md12">
	        <label class="layui-form-label tec-label-four">图片上传:</label>
	        <button type="button" class="layui-btn four floatLeft" id="rotationUpload">上传</button>
	    </div>
	</div>
	
	<div class="layui-layer-btn layui-layer-btn- btnFixed layerBtnCenter btn-box btn-box-1">
	    <a class="layui-layer-btn0" id="back">取消</a>
	    <a class="layui-layer-btn1" id="updateRotation" >确定</a> 
	    <button class="layui-btn" type="button" style="display: none" id="uploadRotation" >real确定</button>
	</div>
</form>

JS代码
有必要说明一下,这里的逻辑。首先 upload.render 绑定的 rotationUpload 上传按钮,将图片加载到前端,预览方法为 obj.preview ,但此时并没有 触发上传方法homeRotation/uploadImg, 真正触发上传方法的是 uploadRotation 按钮。所以在点击 updateRotation 确定(即保存或修改时),才将预览的图片上传到指定位置 。然后上传图片和保存轮播数据 是两个方法,即上传图片ajax成功之后的回调函数再发送 保存数据的ajax。其他的就是 保存 有三种状态有轮 只修改图片, 只修改数据, 既修改图片又修改数据,判断好就行了。

 	//上传图片
    var uploadInst = upload.render({
        elem: '#rotationUpload'  // 图片上传按钮
        ,url: Hussar.ctxPath+ '/homeRotation/uploadImg'
        ,auto: false             // 不自动上传
        ,multiple: false          // 是否允许上传多张图片
        ,accept: 'file'
        // ,exts: 'png|jpg|bmp|jfif' 			//设置只能上传图片格式文件
        ,size: 50000 				//最大允许上传的文件大小
        ,bindAction: '#uploadRotation'     // 绑定上传按钮
        ,choose: function (obj) {
            //预读本地文件示例,不支持ie8
            obj.preview(function (index, file, result) {
                $('#imgName').val(file.name); //图片名字
                imageName = file.name;
                $('#demo1').attr('src', result); //图片链接(base64)
            });
        }
        , done: function (res) {  // 成功之后的回调函数
            if (res.code === 200){
                $("#realPath").val(res.realPath);
                var ajax = new $ax(Hussar.ctxPath + "/homeRotation/preserveRotation",
                   function (data) {
                        if (data.code === 200){
                            Hussar.success(data.message);
                            jumpToListPage(); // 回到列表页面
                        }else {
                            Hussar.error(data.message);
                        }
                    },function (data) {
                        Hussar.error('提交失败!' + data.message + '!');
                    });
                ajax.setData(JSON.stringify(
                    {
                        pic: $("#realPath").val(),
                        title: $("#title").val(),
                        noticeName: $("#noticeName").val(),
                        noticeId: $("#noticeId").val(),
                        noticeUrl: $("#noticeUrl").val(),
                        noticeType: $("#noticeType").val(),
                        page: $("#page").val()
                    }));
	             }
	             ajax.setContentType('application/json');
	             ajax.start();
            }else{
                return Hussar.error(res.message);
            }
        }
        , error: function () {     //失败之后的回调函数,并实现重传
            var demoText = $('#demoText');
            demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-mini demo-reload">重试</a>');
            demoText.find('.demo-reload').on('click', function () {
                uploadInst.upload();
            });
        }
    })

	 // 新增轮播 保存按钮
       $("#addRotation").click(function () {
       		// 数据校验的方法,根据需要来
            if (rotationValidation()&&homeRotationConfigureHandling.check()){
                var operation = function () {
                    $("#noticeUrl").val(homeRotationConfigureHandling.seItem.noticeUrl),
                    $("#noticeType").val(homeRotationConfigureHandling.seItem.noticeType),
                    $("#noticeId").val(homeRotationConfigureHandling.seItem.proId),
                    $("#title").val(homeRotationConfigureHandling.seItem.pName),
                    $("#uploadRotation").click();  // 就是这里,触发图片上传
                };
                Hussar.confirm('确定要保存吗?',operation);
            }
       })

	// 回到列表页面
    function jumpToListPage() {
        setTimeout(function () {
            if (window.parent == window) {
                window.location.href = window.location;
            } else {
                var ifrmes = window.parent.document.getElementsByTagName("iframe");
                for (var i = 0; i < ifrmes.length; i++) {
                    var iframeObj = ifrmes[i];
                    if (iframeObj.src.indexOf('/homeRotation/toHomeRotationIndex') != -1) {
                        iframeObj.src = iframeObj.src;
                        window.parent.HussarTab.tabChange(iframeObj.getAttribute("tab-id"))
                        break;
                    }
                }
                window.parent.HussarTab.tabDelete(window.frameElement.getAttribute("tab-id"));
            }
        }, 2000);
    }

Controller层代码

	/**
     * 上传图片
     * @param multipartFile
     * @return
     * @throws Exception
     */
    @RequestMapping("/homeRotation/uploadImg")
    @ResponseBody
    public JSONObject uploadImg(@RequestParam("file") MultipartFile multipartFile) throws Exception {
        return iHomeRotationService.uploadRotationImg(multipartFile);
    }
   /**
     * 新增一条 轮播数据
     * @param rotationInfoVO
     * @return
     */
    @RequestMapping("/preserveRotation")
    @ResponseBody
    public Tip preservationRotation(@RequestBody RotationInfoVO rotationInfoVO){
        return iHomeRotationService.insertRotation(rotationInfoVO);
    }

Service层代码
链接的全拼包含 敏感字段( noticeId),需要加密起来,其方法为
encrypt = DesUtil.encrypt(RotationNoticeUtil.ROTATION_DEC_PWD, rotationInfoVO.getNoticeId());

	 /**
     * 上传轮播图片,其核心就是 multipartFile.transferTo(newFile);
     * @param multipartFile
     * @return
     */
    @Override
    public JSONObject uploadRotationImg(MultipartFile multipartFile) throws Exception {
        JSONObject json = new JSONObject();
        if (!StringUtils.isEmpty(String.valueOf(multipartFile)) && multipartFile.getSize() > 0) {
            String id = UUID.randomUUID().toString().replaceAll("-", ""); // 随机生成id
            String fileName = multipartFile.getOriginalFilename(); // 获取上传的文件的文件名
            String suffix = fileName.substring(fileName.lastIndexOf(".")); // 获取 文件的后缀 (例 .png 这种)
            //检查文件名是否包含xss脚本
            String xss = XssCheckerUtils.checkXss(fileName);
            if (!org.apache.commons.lang3.StringUtils.isEmpty(xss)) {
                throw new ApiException(HttpCode.BAD_REQUEST.value(), "invalid request , xss code:" + xss);
            }
            try {
                // 系统上传的路径
                String fileSavePath = this.hussarProperties.getFileUploadPath();
                fileSavePath = fileSavePath.substring(0,fileSavePath.length()-1);
                String realPath = fileSavePath + "/" +id + suffix;  // 上传的文件全拼
                File newFile = new File(realPath);
                multipartFile.transferTo(newFile);  // 上传的主方法
                json.put("code",200);
                json.put("message","上传成功!");
                json.put("realPath",realPath);
                json.put("id",id);
                return json;
            } catch (IOException e) {
                throw new HussarException(BizExceptionEnum.UPLOAD_ERROR);
            }
        } else {
            json.put("code",233);
            json.put("message","文件为空!");
            return json;
        }
    }

	/**
     * 新增一条 轮播数据,写这个主要是因为有个对noticeId的加密
     * @param rotationInfoVO
     * @return
     */
    @Override
    public Tip insertRotation(RotationInfoVO rotationInfoVO) {
        String encrypt = "";
        if (!rotationInfoVO.getNoticeId().isEmpty()){
            // 对 noticeId 加密,得到密文 拼接到 url
            encrypt = DesUtil.encrypt(RotationNoticeUtil.ROTATION_DEC_PWD, rotationInfoVO.getNoticeId());
        }
        rotationInfoVO.setId( UUID.randomUUID().toString().replaceAll("-", ""));
        String url = "";
        // 项目中所有的公示公告及法规等,跳转的href有三种情况,需做判断
        if ((rotationInfoVO.getNoticeType() == null || rotationInfoVO.getNoticeType().isEmpty())
                && (rotationInfoVO.getNoticeId()== null || rotationInfoVO.getNoticeId().isEmpty())){
            url = rotationInfoVO.getNoticeUrl();
        }else if (rotationInfoVO.getNoticeType() == null || rotationInfoVO.getNoticeType().isEmpty()){
            url = rotationInfoVO.getNoticeUrl() + "?pId="+encrypt;
        }else {
            url = rotationInfoVO.getNoticeUrl() + "?pId="+encrypt+"&type="+rotationInfoVO.getNoticeType();
        }
        rotationInfoVO.setUrl(url);
        rotationInfoVO.setCreatTime(new Date(System.currentTimeMillis()));
        rotationInfoVO.setCreatUser(ShiroKit.getUser().getName());
        rotationInfoVO.setRotationStatus("0");
        rotationInfoVO.setDel("0");
        boolean b = false;
        try {
            b = iHomeRotationConfigureMapper.insertRotation(rotationInfoVO);
        }catch (Exception e){
            return new ErrorTip(HttpCode.INTERNAL_SERVER_ERROR.value(),"数据错误!");
        }
        if (b){
            Tip successTip = new SuccessTip();
            successTip.setMessage("添加成功!");
            return successTip;
        }else {
            return new ErrorTip(HttpCode.CONFLICT.value(),"添加失败!");
        }
    }

3.LayUI数据表格加载时自动选中
当修改某条轮播时,之前绑定的数据需要在页面刚加载的时候就绑定上,所以这里有必要说一下自动选中的问题。主要方法 parseData:function

JS代码

table.render({
    elem: '#uploadList'
    ,height:393
    ,url: ctxPath + ''
    ,method: 'POST'
    ,contentType : "application/json;charset=UTF-8"
    ,cols:[[
        {type: 'checkbox', fixed: 'left'},
        {title: '序号',type : 'numbers',align:"center" ,halign:'center',width: 48},
        {title: '主键',width:'0%', field: 'proId',hide: true, align: 'center',halign:'center'},
        {title: '标题', field:'pName', align: 'center',halign:'center'},
        {title: '创建时间', field:'createTime', align: 'center',halign:'center',sort:true},
        {title: '公告Url',width:'0%', field: 'noticeUrl',hide: true, align: 'center',halign:'center'},
        {title: '公告类型',width:'0%', field: 'noticeType',hide: true, align: 'center',halign:'center'},
    ]]
    ,limit: 10
    ,page: true
    ,even: true
    ,where: {}
    ,done: function (res, curr, count) { //修改表头颜色
        $('th').css({ 'background-color':'#a4dacd','color':'#000','font-size':'14px'});
        $('th div').css('text-align', 'center');
    }
    ,loading: true
    // 数据格式解析的回调函数,选中的轮播的基本数据存在window全局变量中。
    ,parseData:function(res){
        var data = res.data;
        if (window.type == "update"){
            for (let i = 0; i < data.length; i++) {
                if ( window.noticeTitle == data[i].pName && window.noticeUrl == data[i].noticeUrl){
                    data[i]["LAY_CHECKED"] = true;  // 设置 选中
                }
            }
        }
        return {  //将重新处理好的数据传给表格以完成渲染
            "code": res.code,
            "count": res.count,
            "data": data
        };
    }
});
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值