分类 代码 下的文章

  • html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>摄像头拍照上传</title>
</head>

<body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

<video id="video" width="480" height="320" controls>
</video>
<div>
    <button id="capture">拍照</button>
</div>
<canvas id="canvas" width="480" height="320"></canvas>
<script>

    //访问用户媒体设备的兼容方法
    function getUserMedia(constraints, success, error) {
        if (navigator.mediaDevices.getUserMedia) {
            //最新的标准API
            navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
        } else if (navigator.webkitGetUserMedia) {
            //webkit核心浏览器
            navigator.webkitGetUserMedia(constraints, success, error)
        } else if (navigator.mozGetUserMedia) {
            //firfox浏览器
            navigator.mozGetUserMedia(constraints, success, error);
        } else if (navigator.getUserMedia) {
            //旧版API
            navigator.getUserMedia(constraints, success, error);
        }
    }

    let video = document.getElementById('video');
    let canvas = document.getElementById('canvas');
    let context = canvas.getContext('2d');

    function success(stream) {
        //兼容webkit核心浏览器
        let CompatibleURL = window.URL || window.webkitURL;
        //将视频流设置为video元素的源
        console.log(stream);

        //video.src = CompatibleURL.createObjectURL(stream);
        video.srcObject = stream;
        video.play();
    }

    function error(error) {
        console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
    }

    if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator
        .mozGetUserMedia) {
        //调用用户媒体设备, 访问摄像头
        getUserMedia({
            video: {
                width: 480,
                height: 320
            }
        }, success, error);
    } else {
        alert('不支持访问用户媒体');
    }


    document.getElementById('capture').addEventListener('click', function () {
        context.drawImage(video, 0, 0, 480, 320);
        var base64 = canvas.toDataURL('png');
        console.log(base64);

        $.ajax({
            url: "save.php",
            type: "POST",
            data: {
                image_base: base64
            },
            dateType: 'formData',
            enctype: 'multipart/form-data',
            async: false,
            success: function (result) {
                console.log(result);
            }
        });
    })
</script>
</body>

</html>
  • php
<?php

function format($base64)
{
    if (($l = strpos($base64, ';base64,')) !== false) {
        $p = explode('/', substr($base64, 0, $l));
        if (!empty($p[1])) {
            return '.' . $p[1];
        }

    }
    return '.unknown';
}

//echo $base64;
//  $base64是获取到前端传递的src里面的值,也就是我们的数据流文件
$base64 = $_POST['image_base'];
//  设置文件路径和文件前缀名称
$path = "./";
$prefix = 'nx_';
$output_file = $prefix . time() . rand(100, 999) . format($base64);
// 'data:image/png;base64,'
$base64 = str_replace(substr($base64, 0, strpos($base64, ';base64,') + 8), '', $base64);
$path = $path . $output_file;
//  创建将数据流文件写入我们创建的文件内容中
$ifp = fopen($path, "wb");
fwrite($ifp, base64_decode($base64));
fclose($ifp);
// 第二种方式
// file_put_contents($path, base64_decode($base64));
// 输出文件
echo json_encode([
    'message' => '上传成功',
    'save_file' => $output_file,
], 256);
exit;

PSR编码规范简述

PSR

psr-0 自动加载

psr-1 基本代码规范

  • 文件内只出现 <?php<?= 标签 (必须)
  • 只是用utf-8 没有BOM头的php代码 (必须)
  • 声明新的类型符,不产生副作用
  • 命名空间遵循autoload自动加载psr-0/4规范(必须)
  • 类名驼峰(必须)
  • 类中的常量下划线_分隔(必须)
  • 方法驼峰(必须)

psr-2 代码样式

  • 必须遵循psr-1
  • 四个空格,而非tab
  • 限制每行长度 80或者更少
  • namespace 和 use 必须空格
  • 类的括号必须独立一行
  • 类的方法也一样
  • 所有的属性和方法必须在修饰符之前,static在之后
  • 关键词之后必须有空格
  • 代码流程控制,{ 在一行,}独立一行
  • {之后没有空格,}之前没有空格

psr-3 日志接口

  • 错误级别RFC 5424 (debug, info, notice, warning, error, critical, alert,
    emergency)

psr-4 自动加载

相比于 psr-0 规范比较干净 PSR-0规范中下划线_会被转化成为目录分割线
上面有详细的介绍,这里就不再重复

psr-6 缓存接口

psr-7 http消息接口

psr-11 容器接口

psr-13 超媒体链接

psr-15 http句柄

psr-16 简单缓存

  • 前言

    首先这种问题一般不会出现, 但是这个代码是别人写的, 里面相关的情况不是很清除, 网上的答案有很多,  包括在 `config/app.php` 里面在启动的时候被注册了导致的, 我顺着这个放心也查了很久, 最后找到原因, 答案不是这个
  • 错误源以及错误表现

    执行 `composer install -vvv` 到最后一步时就报错, 错误内容为代码报错, 代码内容大概是服务间登录, 获取token, 然后在配置不存在或者配置的地址不能联网的情况下, 执行这个服务间登录的代码, 就会取不到数据, 那段代码直接去返回的数组的键值, 然后出现了报错
    简单来说, 那个服务间的类被实例化就会出错, 因为实例化的时候调用了服务间登录的方法
  • 检查方向

    1. 网上的答案有很多,包括在 `config/app.php` 里面在启动的时候被注册了导致的, 我顺着这个放心也查了很久
    2. 然后我就把检索了所有的代码文件, 看看哪些地方使用了这个类, 后来发现在 `\App\Console\Commands\FixData.php` 中发现了可以的地方, 这个目录下的文件显然是一个自定义命令文件, 在执行laravel的方法时, 所有的命令都会被预加载, 预加载就以为命令中的 `__construct()` 方法, 这个方法体执行了实例化了那个服务间的类文件
  • 测试 (证明猜想)

    1. 我把那个文件中实例化这个服务间的类给注释掉, 再加一行var_dump([6666]), 重新执行 `composer install` 后不再报错了, 同时打印我调试的值, 正常运行完成
    2. 我把那个自定义命令文件的类后面的 `extends Command` 的前面加上注释, 重新执行了测试, 不在被执行这个类了, 我看了下这个自定义类的代码,是用于数据库迁移用途的,所以就这样注释下简单的解决了每次启动服务都实例化的问题
  • 总结

    laravel中的需要注意, 自定义命令在执行composer install的时候会被扫描, 其中的 所有命令文件中的 `__construct()` 方法都会被实例化

  • index.html

    <script src="export_html_table_csv.js"></script>
    
    <div class="auto_table">
        <script>
            if(typeof openNewTargetHtml == "undefined") {
                function openNewTargetHtml(thiss){
                    var html = thiss.parentNode.parentNode.parentNode.parentNode.children[1].firstElementChild.firstElementChild.innerHTML;
                    var newwindow = window.open("", "_blank","");
                    newwindow.document.write(html);
                }
            }
        </script>
        <script>
            if(typeof exportCSV == "undefined") {
                function exportCSV(thiss){
                    var tableObj = thiss.parentNode.parentNode.parentNode.parentNode.children[1].firstElementChild.firstElementChild.firstElementChild;
                    downloadCSV(tableObj,'aa.csv');
                }
            }
        </script>
    
    
        <style>
            tr,td{
                border: 1px solid #9E9E9E;
                text-align: center;
            }
            table>thead>tr>td{
                padding: 10px;
            }
            table>tbody>tr>td{
                border: 1px solid #9E9E9E;
            }
            table>tbody>tr{
                border: 1px solid #9E9E9E;
            }
        </style>
        <script>
            if(typeof openNewTargetHtml == "undefined") {
                function openNewTargetHtml(thiss){
                    var html = thiss.parentNode.parentNode.parentNode.parentNode.children[1].firstElementChild.firstElementChild.innerHTML;
                    var newwindow = window.open("", "_blank","");
                    newwindow.document.write(html);
                }
            }
        </script>
    
        <style>
            tr,td{
                border: 1px solid #9E9E9E;
                text-align: center;
            }
            table>thead>tr>td{
                padding: 10px;
            }
            table>tbody>tr>td{
                border: 1px solid #9E9E9E;
            }
            table>tbody>tr{
                border: 1px solid #9E9E9E;
            }
        </style>
        <table class="MsoNormalTable"  border="0" cellspacing="0" cellpadding="0" style="margin: 10px; padding-left: 50%;border-collapse:collapse;font-size: larger;" ><thead><tr><td>用户访问历史 <font style="color: red;">(9)rows </font> <button type="button" onclick="openNewTargetHtml(this)">新标签页打开</button> <button type="button" onclick="exportCSV(this)">导出CSV</button></td></tr></thead><tbody><tr><td>
    
            <table class="MsoNormalTable"  border="0" cellspacing="0" cellpadding="0" style="margin: 10px; padding-left: 50%;border-collapse:collapse;font-size: larger;" ><thead><tr><td>id</td><td>标""题</td><td>访问时间</td></tr></thead><tbody><tr><td>1333820</td><td>我的\",\"课程</td><td>2020-08-31 21:01:17</td></tr><tr><td>1244314</td><td>如何实现全赢人生 - 奇迹30</td><td>2020-08-29 20:42:20</td></tr><tr><td>1244309</td><td>支付完成</td><td>2020-08-29 20:42:06</td></tr><tr><td>1244305</td><td>支付,订单</td><td>2020-08-29 20:41:55</td></tr><tr><td>1244304</td><td>支付订单</td><td>2020-08-29 20:41:55</td></tr><tr><td>1244299</td><td>如何实现全赢人生 - 奇迹30</td><td>2020-08-29 20:41:41</td></tr><tr><td>1244294</td><td>课程券中心</td><td>2020-08-29 20:41:25</td></tr><tr><td>1243967</td><td>首页</td><td>2020-08-29 20:32:13</td></tr><tr><td>1243960</td><td>奇迹30</td><td>2020-08-29 20:32:07</td></tr></tbody></table></td></tr></tbody></table></div>
    <style>
        table{
            display: inline-table;
        }
    </style>
  • export_html_table_csv.js 文件

    if (typeof downloadCSV == "undefined") {
        function downloadCSV(tableid, title) {
            var winname;
            try {
                if (navigator.userAgent.indexOf("MSIE") > 0) { //IE浏览器
                    alert("该功能为兼容 IE浏览器, 请使用谷歌浏览器");
                } else if (isFirefox = navigator.userAgent.indexOf("Firefox") > 0) { //Firefox
                    alert("该功能为兼容 Firefox, 请使用谷歌浏览器");
                } else { //Google Chrome
                    //alert("Google Chrome等浏览器");
                    var str = getTableData(tableid, this);
                    //支持中文
                    var uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
                    var downloadLink = document.createElement("a");
                    downloadLink.href = uri;
                    downloadLink.download = title + ".csv";
                    document.body.appendChild(downloadLink);
                    downloadLink.click();
                    document.body.removeChild(downloadLink);
                }
            } catch (e) {
                alert(e.Message);
                return false;
            }
            return false;
        }
    }
    
    if (typeof getTblData == "undefined") {
        // 传入html中的table对象
        function getTableData(curTbl, inWindow) {
            var rows = 0;
            var tblDocument = document;
            tblDocument = eval(inWindow).document;
            // var curTbl = tblDocument.getElementById(inTbl);
            var outStr = "";
            var rowStr = "";
            if (curTbl != null) {
                for (var j = 0; j < curTbl.rows.length; j++) {
                    for (var i = 0; i < curTbl.rows[j].cells.length; i++) {
    
                        if (i == 0 && rows > 0) {
                            outStr += ",";
                            rows -= 1;
                        }
                        rowStr = curTbl.rows[j].cells[i].innerText;
                        if (rowStr.indexOf('"') != -1) {
                            rowStr = rowStr.replace(/"/g, '""');
                            rowStr = '"' + rowStr + '"';
                        } else if (rowStr.indexOf(',') != -1) {
                            rowStr = '"' + rowStr + '"';
                        }
                        outStr += rowStr + ",";
                        if (curTbl.rows[j].cells[i].colSpan > 1) {
                            for (var k = 0; k < curTbl.rows[j].cells[i].colSpan - 1; k++) {
                                outStr += ",";
                            }
                        }
                        if (i == 0) {
                            if (rows == 0 && curTbl.rows[j].cells[i].rowSpan > 1) {
                                rows = curTbl.rows[j].cells[i].rowSpan - 1;
                            }
                        }
                    }
                    outStr += "\r\n";//换行
                }
            } else {
                outStr = null;
                alert(allPage.noData);
            }
            return outStr;
        }
    }

  • in_array 踩坑
如果写法 in_array('*',$arr);  这种写法是错误的, 如果 $arr=[0]; 该判断就为true了
正确写法 !empty(array_instract(["*"],$arr)); 通过判断交集是否为空来判断更准确, 避免数组中包含 0 时导致字符串in_array都为true的情况