Solved: The front-end direct transfer to Ali oss reported an error cross-domain problem, "No 'Access-Control-Allow-Origin'", this error is basically because there is no rule configuration on Ali's open platform (attached my packaged upload source code)

 Solution (my packaged upload code is in the "Encapsulated Upload" section below):

Just go directly to the Ali OSS management background to add a cross-domain rule: see the picture for details

 Configure it like this and click OK, it’s that simple

Incident background:

The title is already the answer, but with my personality, I still want to introduce the background of the crime. If you are in a hurry, you can jump directly to the solution:

Originally, I was working on the front-end, and I also worked on the Android side (why not ios, because I have no money to buy a mac), and then I only care about the three-acre area of ​​​​vue and js, what server configuration, Alibaba Cloud oss, and I have nothing to do. It doesn't matter. Until our boss used our website and reported an error when uploading a large file, the back-end test said that there was no problem (the back-end was tested with a small file, this file was originally sent by the boss, but after the boss sent it on WeChat, it may be compressed A lot, which caused him to upload successfully), and then I uploaded it with a large video, and found that a timeout error was reported. The upload we used was the upload interface written by the backend. The interface error should be resolved by the interface in theory, but the interface may have been resolved for a long time It is not very easy to solve this problem. After a long time, it has not been improved. The boss said that in the future, the front-end will be used to upload oss ​​directly. Doesn’t this have to be uploaded?

Then I encountered the cross-domain problem mentioned in the title, explain it:

This error is due to CORS (Cross-Origin Resource Sharing) policy. CORS is a browser security mechanism used to limit cross-origin requests and prevent malicious websites from sending requests to obtain sensitive data. When the browser initiates a request to a domain name different from the current domain, the server needs to set the CORS response header to allow cross-domain requests.

Access to XMLHttpRequest at 'xxx' from origin 'http://localhost:8023' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

After I checked Baidu, I told the backend that you need to configure it in this way, and then he configured it for a long time, and said yes, I said it is still cross-domain, and the backend said, I am right here, I have logged in and configured it for you. You can try this js demo, he sent me a plupload demo, and I found that it can be uploaded after running, I think that should be my problem, and then I see the effect of his operation, it is very good, and can monitor upload Progress, eh, wait, upload progress? Isn't that unique to multi-part uploads? Part-by-part uploads can indeed avoid cross-domain detection, because the size of each part is not enough to trigger the browser's same-origin detection. Co-authoring did not solve the problem, but the backend let me go around in a big circle to upload. I think it’s fine to upload it, whatever the other way, and then I looked at the plupload code, I’m so scared, if I use this method in the future, I’ll have to suffer, because it’s only suitable for native, for this kind of vue The two-way binding mode is completely unfriendly, because it even has to pass the tag id as a parameter. If it is used for every upload, it will be a headache. Let me show you this part of the plupload code. This code can be simplified, but It's still very troublesome, and it can't be simplified too much. If you are interested, you can take a look:

import plupload from 'plupload';

let accessid = ''
let accesskey = ''
let host = ''
let policyBase64 = ''
let signature = ''
let callbackbody = ''
let filename = ''
let key = ''
let expire = 0
let g_object_name = ''
let g_object_name_type = ''
let timestamp = ''
let now = timestamp = Date.parse(new Date()) / 1000;

function send_request() {
    var xmlhttp = null;
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }

    if (xmlhttp != null) {
        // serverUrl是 用户获取 '签名和Policy' 等信息的应用服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
        let serverUrl = 'xxx'
        xmlhttp.open("GET", serverUrl, false);
        xmlhttp.send(null);
        return xmlhttp.responseText
    } else {
        alert("Your browser does not support XMLHTTP.");
    }
}
function get_signature() {
    // 可以判断当前expire是否超过了当前时间, 如果超过了当前时间, 就重新取一下,3s 作为缓冲。
    now = timestamp = Date.parse(new Date()) / 1000;
    if (expire < now + 3) {
        let body = send_request()
        var obj = eval("(" + body + ")");
        host = obj['host']
        policyBase64 = obj['policy']
        accessid = obj['accessid']
        signature = obj['signature']
        expire = parseInt(obj['expire'])
        callbackbody = obj['callback']
        key = obj['dir']
        return true;
    }
    return false;
}

function calculate_object_name(filename) {
    // if (g_object_name_type == 'local_name') {
    //   g_object_name += "${filename}"
    // } else if (g_object_name_type == 'random_name') {
    let suffix = get_suffix(filename)
    g_object_name = key + random_string(10) + suffix
    // }
    return ''
}

function get_uploaded_object_name(filename) {
    if (g_object_name_type == 'local_name') {
        let tmp_name = g_object_name
        tmp_name = tmp_name.replace("${filename}", filename);
        return tmp_name
    } else if (g_object_name_type == 'random_name') {
        return g_object_name
    }
}

function set_upload_param(up, filename, ret) {
    if (ret == false) {
        ret = get_signature()
    }
    g_object_name = key;
    if (filename != '') {
        let suffix = get_suffix(filename)
        calculate_object_name(filename)
    }
    let new_multipart_params = {
        'key': g_object_name,
        'policy': policyBase64,
        'OSSAccessKeyId': accessid,
        'success_action_status': '200', //让服务端返回200,不然,默认会返回204
        'callback': callbackbody,
        'signature': signature,
    };

    up.setOption({
        'url': host,
        'multipart_params': new_multipart_params
    });

    up.start();
}

function check_object_radio() {
    var tt = document.getElementsByName('myradio1');
    for (var i = 0; i < tt.length; i++) {
        if (tt[i].checked) {
            g_object_name_type = tt[i].value;
            break;
        }
    }
}

function random_string(len) {
    len = len || 32;
    var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
    var maxPos = chars.length;
    var pwd = '';
    for (var i = 0; i < len; i++) {
        pwd += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
}

function get_suffix(filename) {
    let pos = filename.lastIndexOf('.')
    let suffix = ''
    if (pos != -1) {
        suffix = filename.substring(pos)
    }
    return suffix;
}

/**
 * 初始化上传插件
 */
function initPlUploader(lthis) {
    var uploader = new plupload.Uploader({
        runtimes: "html5,flash,silverlight,html4",
        browse_button: "courseSelectFile",
        //multi_selection: false,
        // container: document.getElementById('container'),
        // flash_swf_url : 'lib/plupload-2.1.2/js/Moxie.swf',
        // silverlight_xap_url : 'lib/plupload-2.1.2/js/Moxie.xap',
        url: "http://oss.aliyuncs.com",

        filters: {
            mime_types: [
                //只允许上传图片和zip文件
                {title: "Video files", extensions: "mp4,avi,wmv,mov,flv,rmvb,3gp,m4v,mkv"},
                // { title: "Zip files", extensions: "zip,rar,ipa" }
            ],
            max_file_size: "10000mb", //最大只能上传10mb的文件
            prevent_duplicates: false //不允许选取重复文件
        },

        init: {
            PostInit: function () {
                document.getElementById("ossfile").innerHTML = "";
                document.getElementById("postfiles").onclick = function () {
                    set_upload_param(uploader, "", false);
                    return false;
                };
            },

            FilesAdded: function (up, files) {
                plupload.each(files, function (file) {
                    document.getElementById("ossfile").innerHTML +=
                        '<div id="' +
                        file.id +
                        '">' +
                        file.name +
                        " (" +
                        plupload.formatSize(file.size) +
                        ")<b></b>" +
                        '<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>' +
                        "</div>";
                });
                document.getElementById("postfiles").click()
            },

            BeforeUpload: function (up, file) {
                check_object_radio();
                set_upload_param(up, file.name, true);
                lthis.subsectionFormValidate.subsectionName = file.name.substring(0, file.name.lastIndexOf("."))
            },

            UploadProgress: function (up, file) {
                var d = document.getElementById(file.id);
                d.getElementsByTagName("b")[0].innerHTML =
                    "<span>" + file.percent + "%</span>";
                var prog = d.getElementsByTagName("div")[0];
                var progBar = prog.getElementsByTagName("div")[0];
                progBar.style.width = 2 * file.percent + "px";
                progBar.setAttribute("aria-valuenow", file.percent);
            },

            FileUploaded: function (up, file, info) {
                if (info.status == 200) {
                    // document
                    //     .getElementById(file.id)
                    //     .getElementsByTagName("b")[0].innerHTML =
                    //     "upload to oss success, object name:" +
                    //     get_uploaded_object_name(file.name) +
                    //     " 回调服务器返回的内容是:" +
                    //     info.response;
                    lthis.subsectionFormValidate.videos.push(JSON.parse(info.response))
                    lthis.$Message.success('视频上传成功')
                    lthis.save(3)
                } else if (info.status == 203) {
                    document
                        .getElementById(file.id)
                        .getElementsByTagName("b")[0].innerHTML =
                        "上传到OSS成功,但是oss访问用户设置的上传回调服务器失败,失败原因是:" +
                        info.response;
                } else {
                    document
                        .getElementById(file.id)
                        .getElementsByTagName("b")[0].innerHTML = info.response;
                }
            },

            Error: function (up, err) {
                if (err.code == -600) {
                    lthis.$Message.error('文件最大不得超过10G')
                } else if (err.code == -601) {
                    lthis.$Message.error('请上传要求的视频格式文件')
                } else if (err.code == -602) {
                    lthis.$Message.error('这个文件上传过了')
                } else {
                    lthis.$Message.error('错误:' + err.response)
                }
            }
        }
    });
    uploader.init();
}

If this method is used for every upload, with my limited ability, it will exhaust me to death. Then I asked the backend to continue to modify the oss configuration, and the backend said: OK, let me take a look, okay, I will go up and take a look later, hey, I remember that your previous project was uploaded successfully..., the next day, Still failed, I asked the boss for the oss password account to log in and changed the configuration by myself (the backend has always been used to handle server-related configurations), hey, the front-end code didn’t change at all, and the upload was successful.

The following is my own upload part of the code

Package upload:

I use the Ali oss document to sort it out, let the backend write the interface for obtaining the temporary secret key, all of these are completed, I encapsulated a js tool, and contribute it to everyone, just read the comments, my get method is the get in axios method, you can also use axios.get directly

import OSS from 'ali-oss';
import { Toast } from '[email protected]@vant';
import {$get} from "./http";

// 从后端服务获取 STS 临时访问凭证,这个让后端照着阿里云的文档写,拿到一些keyid和临时秘钥啥的
async function getOSSSTS() {
    const res = await $get('/...这里写你自己的接口路径/getOssSTS', {
        params: {
            type: 2
        }
    });
    if (res.code === 200) {
        return res.data;
    } else {
        Toast(res.msg);
    }
}

// 创建阿里云 OSS 客户端实例
async function createOSSClient() {
    const ossSTS = await getOSSSTS();
    return new OSS({
        region: ossSTS.region,
        accessKeyId: ossSTS.accessKeyId,
        accessKeySecret: ossSTS.accessKeySecret,
        stsToken: ossSTS.stsToken,
        bucket: ossSTS.bucket
    });
}

// 上传文件到阿里云 OSS
export async function uploadToOSS(file) {
    const client = await createOSSClient();
    const result = await client.put(file.name, file);
    return result.url;
}

Then here is the call, which uses the synchronous writing of async/await to handle asynchronous requests, which is similar to the feeling of coroutines, which is the syntax of es7. 


this.video = await uploadToOSS(file.file);

It is configured here to directly return the file address url after the upload is successful

You can slap them in the face here. It would be a great honor if it helped you, thank you for your attention.

Guess you like

Origin blog.csdn.net/Spy003/article/details/130426472