NodeJS 如何将文件直接从前端上传到Google Cloud Storage存储桶

rn0zuynd  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(148)

我有一个基本的Express服务器和前端应用程序。当用户单击提交按钮时,我想向Express服务器发送一个请求,该服务器应该反过来为Google Cloud Storage bucket生成一个签名的URL。从Google Cloud Storage成功获取签名URL后,它将被发送回前端,以便使用选定的输入视频文件向存储桶发出写入请求。我见过一些教程能够用AWS S3桶做到这一点,但我找不到一个与谷歌存储桶。我试着用这个代码:

const storage = new Storage({
    projectId: 'something',
    keyFilename: 'test.json'
});

async function generateSignedUrl(bucketName, objectName) {
    const expiration = new Date();
    expiration.setMinutes(expiration.getMinutes() + 15);
  
    const signedUrl = await storage.bucket(bucketName).file(objectName).getSignedUrl({
      version: 'v4',
      action: 'write',
      expires: expiration,
    });
  
    return signedUrl;
  }

// Your route to handle the request for a signed URL
app.get('/signed-url', async (req, res) => {
    const bucketName = 'mycompanytestbucket';
    const objectName = 'your-file-namethree.txt';
    console.log('welcome')
  
    const signedUrl = await generateSignedUrl(bucketName, objectName);
  
    // Console log the signed URL
    console.log(signedUrl);
  
    // Send the signed URL back to the client
    res.send(signedUrl);
  });

在前端:

const response = await fetch('http://localhost:8080/signed-url');
  const signedUrl = await response.text();
  const file = imageInput.files[0]

    const xhr = new XMLHttpRequest();
    xhr.open("PUT", signedUrl, true);
    xhr.onload = () => {
    const status = xhr.status;
    if (status === 200) {
        alert("File is uploaded");
    } else {
        alert("Something went wrong!");
    }
    };

    xhr.onerror = () => {
    alert("Something went wrong");
    };
    xhr.setRequestHeader('Content-Type', file.type);
    xhr.send(file);

但是当我运行代码,选择一个文件,然后点击提交按钮时,我得到了这个错误:

Failed to load resource: http://127.0.0.1:5500/frontend/[%22https://storage.googleapis.com/mycompanybucket/your-file-namethree.txt?X-G the server responded with a status of 405 (Method Not Allowed)

我还启用了Google Cloud Bucket权限中的 allUsers 权限,但它仍然提示相同的错误。
任何关于实现这一目标的指导都将受到高度赞赏:)

vecaoik1

vecaoik11#

尝试在签名URL创建中添加method(它的工作原理与Python类似)。同时添加内容类型

const signedUrl = await storage.bucket(bucketName).file(objectName).getSignedUrl({
      version: 'v4',
      method: 'PUT',
      action: 'write',
      expires: expiration,
      contentType: 'application/octet-stream',
    });

相关问题