TP6.0框架 前端图片压缩成base64位的编码格式后上传到本地服务器

4 篇文章 0 订阅
1 篇文章 0 订阅

web前端图片压缩方法可参考我这边文章:web前端 图片压缩后上传到阿里云oss  

里面引用到的几个js文件可以在我的github上获取

https://github.com/hujinchen/alyoss-compression

结合layui框架使用,效果图

                                   

这里选择图片后,没有立马上传到服务器,先通过一个input隐藏域存储base64的图片编码,当点击确定按钮后,再和其他的参数一起提交。

前端部分代码: 

// 这里是点击数据表格中右侧的编辑按钮,然后弹出一个iframe层的主要方法。
// 监听行工具事件  注:tool 是工具条事件名,goodsTable-lay-filter 是 table 原始容器的属性 lay-filter="对应的值"
table.on('tool(goodsTable-lay-filter)', function (obj) {
    var data = obj.data;
    if (obj.event === 'edit') {
        var id = data.id;   // 商品自增id

        // 通过缓存, 给iframe子页面传对象参数的方法
        sessionStorage.setItem('event', 'edit');
        sessionStorage.setItem('param', JSON.stringify(data));
        layer.open({
            type: 2,
            title: '编辑商品:' + data.ProductName,
            content: 'jumpView?url=goods/goodsEdit', // 新的地址
            area: ['500px', '480px'],
            btn: ['确定', '取消'],
            yes: function (index, layero) {
                var iframeWindow = window['layui-layer-iframe' + index],
                    submitID = 'goodsEditConfirm', // iframe页 确认按钮的id和 lay-filter=的值,要一样的
                    submit = layero.find('iframe').contents().find('#' + submitID);

                // 监听iframe页提交
                iframeWindow.layui.form.on('submit(' + submitID + ')', function (res) {
                    var field = res.field; // 获取iframe页提交的字段
                    field.id = id; // 商品ID
                    $.post({
                        url: "{:url('good/upGoods')}",
                        data: field,
                        success: function (res) {
                            if (res.code != 0) {
                                layer.msg(res.msg, { offset: 't', icon: 2 });
                            } else {
                                layer.msg('修改成功', { time: 1000, icon: 1 }, function () {
                                    table.reload('goodsTable'); // 数据刷新
                                    layer.close(index); // 关闭弹框
                                })
                            }
                        }
                    });
                });
                // 触发器 注:必需要有,不然监听不到
                submit.trigger('click');
            }
        });
    }
});

iframe层:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>商品编辑 - iframe框</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    {load href="__LAYUIADMIN__/layui/css/layui.css, __STATIC__/css/common.css" /}
</head>

<body class="layui-hide">
    <div class="layui-form layui-form-pane" lay-filter="goodsEditForm" style="padding: 20px 10px;">
        <div class="layui-form-item">
            <label class="layui-form-label">商品名称</label>
            <div class="layui-input-block">
                <input type="text" name="ProductName" lay-verify="required" placeholder="请输入商品名称" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">商品图片</label>
            <div class="layui-input-block">
                <div class="layui-upload-drag" id="goodsImg">
                    <div class="djsc">
                        <i class="layui-icon"></i>
                        <p>点击上传,或将文件拖拽到此处</p>
                    </div>
                    <div class="layui-hide" id="uploadDemoView">
                        <!-- 这个input隐藏域是用来保存选择图片后的base64的图片编码 -->
                        <input type="hidden" name="goods_imgurl" class="goods_imgurl">
                        <img src="" alt="上传成功后渲染" style="max-width: 196px">
                    </div>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">国际码</label>
            <div class="layui-input-block">
                <input type="text" name="UPCNo" placeholder="请输入国际码" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">品牌名称</label>
            <div class="layui-input-block">
                <input type="text" name="BrandName" placeholder="请输入品牌名称" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">类别名称</label>
            <div class="layui-input-block">
                <input type="text" name="CategoryName" placeholder="请输入类别名称" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">可用库存</label>
            <div class="layui-input-block">
                <input type="number" name="UsableQty" lay-verify="required" placeholder="请输入可用库存" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">价格1</label>
            <div class="layui-input-block">
                <input type="text" name="SalePrice1" lay-verify="price" placeholder="请输入价格,最多保留两位小数点"
                    class="layui-input">
            </div>
        </div>
        
        <!-- 这里就不把所有的代码都贴出来了...... -->
    </div>

    <!-- 以下是为了兼容浏览器 可以使用ES6语法 -->
    {js href="__STATIC__/js/browser.min.js" /}
    {js href="__STATIC__/js/polyfill.min.js" /}
    {js href="__STATIC__/js/aliyun-oss-sdk.min.js" /}
    <!-- 图片压缩 -->
    {js href="__STATIC__/js/compression.js" /}
    {js href="__LAYUIADMIN__/layui/layui.js" /}
    
    <!-- script类型必须是 type="text/babel" -->
    <script type="text/babel">
        layui.config({ base: '__LAYUIADMIN__/' }).extend({ index: 'lib/index' }).use(['index', 'form', 'laydate', 'upload'], function () {
            var $ = layui.$, form = layui.form, laydate = layui.laydate, upload = layui.upload;

            var event = sessionStorage.getItem('event');
            // 点击编辑进入的
            if (event == 'edit') {
                var param = JSON.parse(sessionStorage.getItem('param'));
                if (param.goods_imgurl) {
                    $('.djsc').addClass('layui-hide');
                    $('#uploadDemoView').removeClass('layui-hide').find('img').attr('src', param.goods_imgurl);
                }
                // 表单赋值
                // goodsEditForm 即 class="layui-form" 所在元素属性 lay-filter="" 对应的值
                form.val("goodsEditForm", param);
            }
            $('body').removeClass('layui-hide').addClass('layui-show');

            // 日期时间选择器  trigger: 'click':点击时禁止日期组件闪动
            laydate.render({ elem: '#date', trigger: 'click' });

            // 点击或拖拽上传
            upload.render({
                elem: '#goodsImg',
                multiple: false,    // 是否允许多文件上传
                field: 'goodsImg',  // 设定文件域的字段名
                size: 2048,  // 限制文件大小,单位 KB
                auto: false, // 是否选完文件后自动上传
                bindAction: 'goodsEditConfirm',  // 指向一个按钮触发上传,一般配合 auto: false 来使用
                choose: function (obj) {
                    // 预读本地文件
                    obj.preview(function (index, file, result) {
                        // console.log(index)  得到文件索引
                        // console.log(file)   得到文件的file对象
                        // console.log(result) 得到文件base64编码,比如图片

                        // 当前图片小于1M 原图上传, 否则压缩上传
                        if (file.size / 1024 <= 1024) {
                            $('.goods_imgurl').val(result);
                        } else {
                            // 压缩文件
                            photoCompress(file, { quality: 0.7 }, function (base64Codes) {
                                // base64Codes 这拿到的就是压缩后的base64图片编码
                                $('.goods_imgurl').val(base64Codes);
                            });
                        }

                        $('.djsc').addClass('layui-hide');
                        $('#uploadDemoView').removeClass('layui-hide').find('img').attr('src', result);
                    });
                }
            });

            // 自定义表单验证规则
            form.verify({
                price: function (value, item) {
                    // 验证金额价格的正则表达式(包括两位小数)
                    var priceReg = /(^[1-9]\d*(\.\d{1,2})?$)|(^0(\.\d{1,2})?$)/;
                    if (value == null || value == "") {
                        return '必填项不能为空';
                    } else if (!priceReg.test(value)) {
                        return '价格格式不正确';
                    }
                },
            })
        })
    </script>
</body>

</html>

tp6框架部分代码:

/**
 * 添加商品
 * @param ProductName 商品名称
 * @param UPCNo 国际码
 * @param BrandName 品牌名称
 * @param CategoryName 类别名称
 * @param UsableQty 可用库存
 * @param SalePrice1 价格1
 * @param SalePrice2 价格2
 * @param SalePrice3 价格3
 * @param ProduceDate 生产日期
 * @param goods_imgurl 商品图片 - base64格式
 */
public function addGoods(string $ProductName, string $UPCNo, string $BrandName, string $CategoryName, int $UsableQty, float $SalePrice1, float $SalePrice2, float $SalePrice3, string $ProduceDate, string $goods_imgurl)
{
    $res = $this->uploadFilesImg($goods_imgurl);
    if ($res['code'] == 0) {
        $Goods = new Goods();
        $Goods->addGoods($ProductName, $UPCNo, $BrandName, $CategoryName, $UsableQty, $SalePrice1, $SalePrice2, $SalePrice3, $ProduceDate, $res['data']);
        return $this->succeed();
    } else {
        return $this->resultJson($res['code'], $res['msg']);
    }
}

/**
 * 修改商品
 * @param id  商品id
 * @param ... 其他参数同上
 */
public function upGoods(int $id, string $ProductName, string $UPCNo, string $BrandName, string $CategoryName, int $UsableQty, float $SalePrice1, float $SalePrice2, float $SalePrice3, string $ProduceDate, string $goods_imgurl)
{
    $res = $this->uploadFilesImg($goods_imgurl);
    if ($res['code'] == 0) {
        // 处理价格为空
        if ($ProduceDate == '' || $ProduceDate == null) {
            $ProduceDate = '0000-00-00 00:00:00';
        }

        $Goods = new Goods();
        $str_goods_imgurl = Goods::where('id', $id)->value('goods_imgurl');

        // 判断图片文件是否存在,存在的话则删除旧的图片
        if ($str_goods_imgurl) {
            $path = app()->getRootPath() . './public/' . explode(Request::domain() . '/', $str_goods_imgurl)[1];
            if (file_exists($path)) {
                unlink($path);
            }
        }

        $Goods->upGoods($id, $ProductName, $UPCNo, $BrandName, $CategoryName, $UsableQty, $SalePrice1, $SalePrice2, $SalePrice3, $ProduceDate, $res['data']);
        return $this->succeed();
    } else {
        return $this->resultJson($res['code'], $res['msg']);
    }
}

/**
 * 主要代码是这段方法,我这边是把图片存放在 /public/static/image/ 中 !!!
 * 上传图片检验 - 图片上传到本地服务器
 * @param goods_imgurl 商品图片 - base64编码格式
 * @return 完整的图片地址(包括域名)
 */
public function uploadFilesImg(string $goods_imgurl)
{
    $base64_img = trim($goods_imgurl);
    $up_dir = app()->getRootPath() . './public/static/image/'; // 图片存放的位置

    // 如果文件夹不存在则创建
    if (!file_exists($up_dir)) {
        mkdir($up_dir, 0777);
    }

    // 正则表达式:判断图片文件类型是否正确
    if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_img, $result)) {
        $type = $result[2];
        if (in_array($type, array('pjpeg', 'jpeg', 'jpg', 'gif', 'bmp', 'png'))) {
            // 图片命名 - 格式如:20200502214128.png
            $imgName = date('YmdHis') . '.' . $type;
            $new_file = $up_dir . $imgName;
            if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_img)))) {
                // 完整的图片地址(包括域名)
                $goodsImgurl = Request::domain() . '/static/image/' . $imgName;
                return ['code' => 0, 'msg' => '图片上传成功', 'data' => $goodsImgurl];
            } else {
                return ['code' => 3003, 'msg' => '图片上传失败'];
            }
        } else {
            return ['code' => 3002, 'msg' => '图片类型错误'];
        }
    } else {
        return ['code' => 3001, 'msg' => '文件错误'];
    }
}

到此就基本结束了~

如果是tp6框架接收文件file对象的方法,可参考官方文档: 上传文件

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
TP6.0中,事件机制是通过事件管理器(Event)来实现的。事件管理器是一个全局单例对象,可以在应用程序的任何地方使用。事件管理器主要负责事件的注册、触发和监听。 以下是TP6.0中事件执行的流程: 1. 注册事件 在应用程序的任何地方,都可以通过事件管理器注册事件。注册事件时,需要指定事件名称和事件处理函数。事件名称可以是任何字符串,事件处理函数可以是闭包、方法或者类静态方法。 例如: ```php // 注册事件 \think\facade\Event::listen('user_login', function ($user) { // 处理用户登录事件 ... }); ``` 2. 触发事件 当应用程序执行到某个置时,可以通过事件管理器触发事件。触发事件时,需要指定事件名称和事件参数。事件参数可以是任何类型的数据。 例如: ```php // 触发事件 \think\facade\Event::trigger('user_login', $user); ``` 3. 执行事件处理函数 当事件被触发时,事件管理器会自动执行注册的事件处理函数。事件处理函数会按照注册的顺序执行,直到所有的事件处理函数都执行完毕。 例如: ```php // 执行事件处理函数 function handleUserLogin($user) { // 处理用户登录事件 ... } ``` 4. 返回事件结果 事件处理函数可以返回任何类型的数据,这些数据会被收集到一个数组中,作为最终的事件结果返回。事件结果可以被其他的事件处理函数使用。 例如: ```php // 返回事件结果 function handleUserLogin($user) { // 处理用户登录事件 ... return ['user' => $user, 'time' => time()]; } ``` 以上就是TP6.0中事件执行的流程。通过事件机制,我们可以实现应用程序的解耦和扩展,让应用程序更加灵活和可维护。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值