昨天遇到了一个后端传输导致nginx502的问题

明天在调整了代码之后,遂将解决方案贴出

前端直传的益处:加重应用服务器的压力,将压力分给了oss 这一点特地是在上传大文件时特地显著的,php是要耗费很大一部分内存去解决前端分片上传来的文件再传输给oss,如果文件特地大,耗时长nginx会间接502 咱们没必要去调整nginx的超时工夫把路走窄了。间接由客户端直传oss吧。

实现后效果图

因为dcat-admin是高度封装的。改它的组件根本不事实,不过$form->view()办法能够引入一个视图文件.我的想法是用vue封装一个上传的组件,而后通过该办法引入。正好laravel提供了前端脚手架laravel mix 整合了vue。

  • laravel版本7.x

#### 开始一套梭

composer require laravel/ui --dev //装置前端脚手架php artisan ui vue //公布vue文件npm installnpm install ali-oss --save //装置oss js-sdknpm install clipboard --save //装置复制插件npm run watch  //命令监督热加载、编译

应用element-ui的组件,所以咱们引入它

npm i element-ui -S

app.js文件全局加载

import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI);import Clipboard from 'clipboard';Vue.prototype.Clipboard=Clipboard;

并新建组件OssFile

<template>    <div>        <el-upload            class="upload-demo"            action=""            ref="upload"            :file-list="fileList"            :limit="2"            :on-change="handleChange"            :on-remove="handleRemove"            :auto-upload="false"            accept=""        >            <el-button slot="trigger" size="small" type="primary">选取文件</el-button>            <el-button style="margin-left: 10px;" size="small" type="success" @click="submitForm">直传oss</el-button>            <el-button style="margin-left: 10px;" size="small" type="success" @click="resumeUpload">持续</el-button>            <el-button style="margin-left: 10px;" size="small" type="success" @click="stopUplosd">暂停</el-button>            <el-button style="margin-left: 10px;" size="small" type="success" @click="abortMultipartUpload">革除切片</el-button>        </el-upload>        <el-progress :percentage="percentage" :status="uploadStatus"></el-progress>        <span            class="copybtn"            @click="copy"            :data-clipboard-text="fileName"        >{{ fileName }}</span>    </div></template><script>import Clipboard from 'clipboard';let OSS = require('ali-oss') // 引入ali-oss插件const client = new OSS({    region: 'oss-cn-shenzhen',//依据那你的Bucket地点来填写    accessKeyId: '',//本人账户的accessKeyId    accessKeySecret: '',//本人账户的accessKeySecret    bucket: '',//bucket名字});export default {    name: "OssFile",    data () {        return {            fileName:"",            fileList:[],            file: null,            tempCheckpoint: null, // 用来缓存以后切片内容            uploadId: '',            uploadStatus: null, // 进度条上传状态            percentage: 0, // 进度条百分比            uploadName: '',  //Object所在Bucket的残缺门路        }    },    mounted() {         window.addEventListener('online',  this.resumeUpload);    },    methods: {        copy()        {            var clipboard = new Clipboard(".copybtn");            clipboard.on("success", (e) => {                this.$message({                    message: '复制胜利',                    type: 'success'                });                // 开释内存                clipboard.destroy();            });            clipboard.on("error", (e) => {                // 不反对复制                this.$message({                    message: '该浏览器不反对主动复制',                    type: 'success'                });                // 开释内存                clipboard.destroy();            });        },        // 点击上传至服务器        submitForm(file) {           this.multipartUpload();        },        // 勾销分片上传事件        async abortMultipartUpload() {            window.removeEventListener('online', this.resumeUpload)            const name = this.uploadName; // Object所在Bucket的残缺门路。            const uploadId = this.upload; // 分片上传uploadId。            const result = await client.abortMultipartUpload(name, uploadId);            console.log(result, '=======革除切片====');        },        // 暂停分片上传。        stopUplosd () {            window.removeEventListener('online', this.resumeUpload) // 暂停时革除工夫监听            let result = client.cancel();            console.log( result, '---------暂停上传-----------')        },        // 切片上传        async multipartUpload () {            if (!this.file) {                this.$message.error('请抉择文件')                return            }            console.log("this.uploadStatus",this.file, this.uploadStatus);            console.log("文件列表:"+this.fileList)            console.log("文件:"+this.file)            this.percentage = 0            try {                //object-name能够自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的模式,实现将文件上传至以后Bucket或Bucket下的指定目录。                let result = await client.multipartUpload(this.file.name, this.file, {                    headers: {                        'Content-Disposition': 'inline',                        'Content-Type': this.file.type //留神:依据图片或者文件的后缀来设置,我试验用的‘.png’的图片,具体为什么下文解释                    },                    progress: (p, checkpoint) => {                        this.tempCheckpoint = checkpoint;                        this.upload = checkpoint.uploadId                        this.uploadName = checkpoint.name                        this.percentage = p * 100                        // console.log(p, checkpoint, this.percentage, '---------uploadId-----------')                        // 断点记录点。浏览器重启后无奈间接持续上传,您须要手动触发上传操作。                    },                    meta: { year: 2020, people: 'dev' },                    mime: this.file.type                });                console.log(result, this.percentage, 'result= 切片上传完毕=');                this.$nextTick(()=>{                    this.fileName = 'https://image.mythinkcar.cn/'+result.name                })                console.log(this.fileName)            } catch (e) {                console.log(e)                window.addEventListener('online',  this.resumeUpload) // 该监听放在断网的异样解决                // 捕捉超时异样。                if (e.code === 'ConnectionTimeoutError') { // 申请超时异样解决                    this.uploadStatus = 'exception'                    console.log("TimeoutError");                }            }        },        // 复原上传。        async resumeUpload () {            window.removeEventListener('online', this.resumeUpload)            if (!this.tempCheckpoint) {                this.$message.error('请先上传')                return            }            this.uploadStatus = null            try {                let result = await client.multipartUpload(this.file.name, this.file, {                    headers: {                        'Content-Disposition': 'inline',                        'Content-Type': this.file.type //留神:依据图片或者文件的后缀来设置,我试验用的‘.png’的图片,具体为什么下文解释                    },                    progress: (p, checkpoint) => {                        this.percentage = p * 100                        console.log(p, checkpoint, 'checkpoint----复原上传的切片信息-------')                        this.tempCheckpoint = checkpoint;                    },                    checkpoint: this.tempCheckpoint,                    meta: { year: 2020, people: 'dev' },                    mime: this.file.type                })                console.log(result, 'result-=-=-复原上传完毕')            } catch (e) {                console.log(e, 'e-=-=-');            }        },        // 抉择文件产生扭转        handleChange(file, fileList) {            this.fileList = fileList.filter(row => row.uid == file.uid)            this.file = file.raw            // 文件扭转时上传            // this.submitForm(file)        },        handleRemove(file, fileList) {            this.percentage = 0 //进度条置空            this.fileList = []        },    }}</script><style>.avatar-uploader .el-upload {    border: 1px dashed #d9d9d9;    border-radius: 6px;    cursor: pointer;    position: relative;    overflow: hidden;}.avatar-uploader .el-upload:hover {    border-color: #409EFF;}.avatar-uploader-icon {    font-size: 28px;    color: #8c939d;    width: 150px;    height: 150px;    line-height: 150px;    text-align: center;}.avatar {    width: 150px;    height: 150px;    display: block;}</style>

app.js中引入组件

Vue.component('oss-file', require('./components/uploads/OssFile.vue').default);

view目录新建oss.blade.php 引入组件 <oss-file></oss-file>

<link rel="stylesheet" href="{{mix('css/app.css')}}"><div id="app"><div class="container">    <oss-file></oss-file></div></div><script src="{{mix('js/app.js')}}"></script>

最初

  $form->html(view('uploads.oss'));  $form->text('link','直传后填入地址');

完满解决~~~

碰到的问题

  • oss 跨域问题
  • oss 呈现 RequestId 错误处理办法 新增`ETag
    x-oss-request-id`

参考文章

  • oss文档
    *阿里 oss 呈现 RequestId 错误处理办法