JavaScript 上传文件 ThinkPHP6 接收保存

默认分类 thinkphp JavaScript 上传文件 axios

记录一下操作.

javaScript

此处以上传微信二维码图片为例

简单实现

使用layui弹窗提示及axios提交数据

<input type="file" onchange="up_do(this)" placeholder="微信号二维码">
<script>
    //解构获取fileList
    up_do = ({files}) => {
        //取到文件
        let file = files[0]
        if (file) {
            //判断文件类型
            if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
                layer.msg('请上传图片')
                return;
            }
            //2M大小限制
            if (file.size > 2 * 1024 * 1024) {
                layer.msg('图片太大')
                return;
            }
            //执行上传操作
            upload(file)
        }
    }
    //上传操作执行
    upload = (file) => {
        //上传文件必须用Form提交,且此处和document.createElement('form')不同.
        let form = new FormData();
        //把文件放进去,字段名file
        form.append('file', file);
        //post提交,文件不能用get,要设置header的Content-Type
        axios.post('/index/upload', form, {header: {"Content-Type": "multipart/form-data"}}).then(({data}) => {
            if (data.code !== 1) {
                layer.msg(data.msg)
                return;
            }
            layer.msg('上传成功')
            
        })
    }
</script>

进阶版

实际的场景是,用户填写表单,点击一个区域上传文件,选择文件确定后,js会生成预览(做判断,图片就直接显示,非图片就根据类型显示预先设置的文件图片)并自动上传后台,并把后台返回的可访问的文件url连接填充到表单内,用户填完数据提交时,文件部分只提交一个URL.

//代码不能直接copy,样式可能是问题
//设置一个方格 中间放上一个灰色云朵表示上传文件区域
<div id="upload" style="display:flex;align-items:center;justify-content:center;height: 150px;width: 150px;padding: 5px;border:1px solid #cccccc;border-radius: 4px;">
    <i class="fa fa-cloud-upload" style="font-size: 30px;color: #cccccc"></i>
</div>
//叉叉按钮区域,上传文件不能只上传,也得给用户删除操作
<div id="clean"></div>
//上传文件的input框
<input style="height: 0;width: 0;padding: 0;margin: 0" type="file" onchange="up_do(this)" id="file">
//此处放上传成功的url,随表单提交
<input  type="hidden" class="form-control" id="wechatqr">
//表单提交按钮
<button type="button" id="create" class="btn btn-info">创建</button>
<script>
    //表单提交操作
    document.getElementById('create').onclick = () => {
        let data = {
             //.....
            'we_chat_qr': document.getElementById('wechatqr').value
        }
        axios.post('', data).then(({data}) => {
            if (data.code !== 1) {
                layer.msg(data.msg)
                return;
            }
            layer.msg('添加成功')
            setTimeout(() => {
                window.location.reload()
            }, 1000)
        })
    }
    //点击图片上传区域等同点击隐藏起来的上传文件的input框
    document.getElementById('upload').onclick = () => document.getElementById('file').click()
    //图片格式和大小判断
    up_do = ({files}) => {
        let file = files[0]
        if (file) {
            if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
                layer.msg('请上传图片')
                return;
            }
            if (file.size > 2 * 1024 * 1024) {
                layer.msg('图片太大')
                return;
            }
            //上传图片操作
            upload(file)
        }
    }

    upload = (file) => {
        //创建form
        let form = new FormData();
        //添加内容
        form.append('file', file);
        //axios提交
        axios.post('/index/upload', form, {header: {"Content-Type": "multipart/form-data"}}).then(({data}) => {
            if (data.code !== 1) {
                layer.msg(data.msg)
                return;
            }
            //上传成功,此处把获得的内容填充到表单的隐藏input框
            document.getElementById('wechatqr').value = data.data.domain + data.data.path;
            //执行预览效果操作
            //FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容
            let reader = new FileReader();
            //异步的,所以不能顺序执行,这里添加一个事件 onload:文件读取成功完成时触发
            reader.onload = () => {
                //预览操作
                preview(reader.result)
            }
            //将文件读取为 DataURL: 'data:image/png;base64,iVBOR.....'
            reader.readAsDataURL(file);

        })
    }

    preview = (url) => {
        //创建x图标
        let i = document.createElement('i')
        i.classList.add('fa')
        i.classList.add('fa-times-circle')
        //图标点击时候所做操作
        i.onclick = () => {
            //清除图片上传区域的图片预览内容
            document.getElementById('upload').innerHTML = '';
            //清除自己
            document.getElementById('clean').innerHTML = '';
            //填充图片上传区域的默认小云朵样式
            document.getElementById('upload').innerHTML = `<i class="fa fa-cloud-upload" style="font-size: 30px;color: #cccccc"></i>`;
            //清除图片链接的input框内容
            document.getElementById('wechatqr').value = '';
        }
        //一些样式
        i.style.fontSize = '25px'
        i.style.width = '25px'
        i.style.height = '25px'
        i.style.textAlign = 'center'
        i.style.lineHeight = '25px'
        i.style.borderRadius = '50%'
        i.style.marginLeft = '-10px'
        i.style.background = 'white'
        i.style.boxShadow = '0px 0px 5px #888888'
        i.onmouseover = () => {
            i.style.boxShadow = '0px 0px 5px #fb7077'
        }
        i.onmouseout = () => {
            i.style.boxShadow = '0px 0px 5px #888888'
        }
        //清除目标区域
        document.getElementById('clean').innerHTML = '';
        //把自己放进去
        document.getElementById('clean').appendChild(i)

        //创建一个img
        let img = document.createElement('img');
        //设置src
        img.src = url;
        //样式
        img.style.maxHeight = '100%'
        img.style.maxWidth = '100%'
        //清除目标区域(灰色云朵或者上个预览图)
        document.getElementById('upload').innerHTML = '';
        //把自己放进去区域内
        document.getElementById('upload').appendChild(img)
    }
</script>

以上是表单添加数据的时候图片上传,在编辑表单数据的时候,表单正常填充,只需要最后判断一下url存在,调用一下preview方法即可正常填充表单

if (res.data.wechatqr) {
    preview(res.data.wechatqr)
}

无图片效果
QQ截图20210820195804.png
选择文件后效果 点击x即可回到上面的无图片效果,也可点击图片继续上传,图片会替换(在填充预览图之前会清空)
QQ截图20210820195821.png

thinkPHP接收文件

先配置好磁盘

在config目录下的filesystem.php配置磁盘

return [
    // 默认磁盘
    'default' => env('filesystem.driver', 'local'),
    // 磁盘列表
    'disks' => [
        'local' => [
            'type' => 'local',
            'root' => app()->getRuntimePath() . 'storage',
        ],
        //磁盘配置名为public
        'public' => [
            // 磁盘类型 (这里对应的其实是一个驱动)
            'type' => 'local',
            // 磁盘路径 (这里是挂载路径 就是public目录,也就是网站可访问的根目录)
            'root' => app()->getRootPath() . 'public',
            // 磁盘路径对应的外部URL路径
            'url' => '/storage',
            // 可见性
            'visibility' => 'public',
        ],
        // 更多的磁盘配置信息
    ],
];

控制器

THinkphp一切都封装好了,很方便

   public function upload()
    {
        //从门面模式的Request取得file字段的文件(对应上面js上传的) 是一个ThinkPHP的File对象
        $file = Request::file('file');
        if (empty($file)) {
            return $this->error('没有上传文件');
        }
        //Filesystem挂载public配置把文件放到配置中定义的磁盘挂载路径下的upload/admin目录内,并返回路径(这里处理一下windows的路径分隔符)
        $patch = '/' . str_replace(DIRECTORY_SEPARATOR, '/', Filesystem::disk('public')->putFile('upload/admin', $file));

        //返回域名及可访问的路径(此处也可自己直接拼接)
        return $this->success('', ['path' => $patch, 'domain' => Request::domain()]);
    }

新评论

称呼不能为空
邮箱格式不合法
网站格式不合法
内容不能为空