1

我想让艺术家客户使用Signed URLs将图像上传到 Cloud Storage 。

以下后端脚本用于获取签名的 url,它位于 Google Cloud 负载平衡器后面:

(这(负载平衡器)会影响什么吗?)

exports.getSignedUrl = async (req, res) => {

    if (req.method !== 'POST') {
        // Return a "method not allowed" error
        return res.status(405).end();
    }
    try {
        console.log("Getting signed url..");

        const storage = new Storage();
        const bucketName = 'bucket' in req.body ? req.body.bucket : 'gsk-public';
        // Get a reference to the destination file in GCS
        const file = storage.bucket(bucketName).file(req.body.filename);
        // Create a temporary upload URL
        const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 100; // Link expires in 1 minute
        const configuration = {
            version: 'v4',
            action: req.body.action,
            expires: expiresAtMs
        };
        if ('type' in req.body) {
            configuration.contentType = req.body.type;
        }
        console.log("Got signed url!");
        const url = await file.getSignedUrl(configuration);
        console.log(url);
        return res.send(url[0]);
    }
    catch (err) {
        console.error(err);
        return res.status(500).end();
    }
};

CORS设置:

[
  {
    "origin": [
      "https://localhost:3000/",
      "https://dreamlouvre-git-development-samuq.vercel.app/"
    ],

    "responseHeader": "*",

    "method": ["GET", "PUT", "POST", "OPTIONS", "HEAD"],

    "maxAgeSeconds": 3600
  }
]

Next.js API 端点来获取签名的 url:

import axios from 'axios';
import {config} from '../config';
import { fileTypeToJPG, createQueryString } from '../../../helpers/helpers';
import mime from 'mime';
export default async (req, res) => {
    if(req.method === 'POST'){
        try{
            if(!config.mimeExtensions.some(el => el===mime.getExtension(req.body.type))){
                //throw new Error('The file type of your image is not supported. Following types are supported: jpg, png, bmp and tiff.');
                return res.status(500).json({ statusCode: 500, message: 'Unsupported filetype.' });
            }
            //console.log('file name: ', req.body.filename);
            //console.log('auth header: ', req.headers.authorization);
            const response = await axios.post(`${config.apiBaseUrl}/auth/signedUrl`, req.body, {headers:{"authorization": `Bearer ${req.headers.authorization}`}});
            //console.log("Respdata");
            //console.log(response.data);
            //console.log(response.data[0]);
            const respData = {
                filename: fileTypeToJPG(req.body.filename),
                originalFileName: req.body.filename,
                url: response.data
            };
            return res.status(200).json(respData);
        }catch (err) {
            //console.log(err);
            return res.status('status' in err ? err.status : 500).json({ statusCode: 500, message: err.message });
        }
    }
    else return res.status(403);
};

Next.js 前端代码放入签名的 url:

const badi = {
  type: file.type,
  filename: fileName,
  action: "write",
  bucket: config.bucketOriginal,
};
console.log("upload 3");
const resp = await axios.post(`/api/auth/getSignedUrl`, badi, {
  headers: { authorization: token },
});
console.log("upload 4", resp.data);
await axios.put(resp.data.url, file, {
  headers: { "Content-type": file.type },
});
  • 观察到的行为:访问已被 CORS 策略阻止。控制台日志upload 4和签名的 url,但签名的 url 不起作用。

  • 预期行为: put 请求将正常工作。

4

1 回答 1

3

到期时间错误可能导致 CORS 错误。我解决了这个问题:

const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 100;

对此:

const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 15*60*1000;

编辑:代码已经开始工作,但现在抛出 403 错误,声称存在格式错误的内容类型标头,尽管没有。请求中存在内容类型标头。

于 2021-12-20T16:21:35.110 回答