web前端图片压缩方法可参考我这边文章:web前端 图片压缩后上传到阿里云oss
里面引用到的几个js文件可以在我的github上获取
结合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对象的方法,可参考官方文档: 上传文件