Javascript 如何使用Node.js将base64编码的图像(字符串)直接上传到Google云存储桶?

Javascript 如何使用Node.js将base64编码的图像(字符串)直接上传到Google云存储桶?,javascript,node.js,google-cloud-storage,google-cloud-platform,Javascript,Node.js,Google Cloud Storage,Google Cloud Platform,目前,我正在使用NPM包将文件直接上传到Google云存储桶。这需要一些技巧,因为我只有图像的base64编码字符串。我必须: 解码字符串 将其另存为文件 将文件路径发送到下面的脚本以上载到Google云存储 删除本地文件 我希望避免将文件完全存储在文件系统中,因为我使用的是Google App Engine,如果删除操作因任何原因无法工作,我不想使文件系统过载/将垃圾文件留在文件系统中。这就是我的上传脚本现在的样子: // Convert the base64 string back to

目前,我正在使用NPM包将文件直接上传到Google云存储桶。这需要一些技巧,因为我只有图像的base64编码字符串。我必须:

  • 解码字符串
  • 将其另存为文件
  • 将文件路径发送到下面的脚本以上载到Google云存储
  • 删除本地文件
我希望避免将文件完全存储在文件系统中,因为我使用的是Google App Engine,如果删除操作因任何原因无法工作,我不想使文件系统过载/将垃圾文件留在文件系统中。这就是我的上传脚本现在的样子:

// Convert the base64 string back to an image to upload into the Google Cloud Storage bucket
var base64Img = require('base64-img');
var filePath = base64Img.imgSync(req.body.base64Image, 'user-uploads', 'image-name');

// Instantiate the GCP Storage instance
var gcs = require('@google-cloud/storage')(),
    bucket = gcs.bucket('google-cloud-storage-bucket-name');

// Upload the image to the bucket
bucket.upload(__dirname.slice(0, -15) + filePath, {
    destination: 'profile-images/576dba00c1346abe12fb502a-original.jpg',
    public: true,
    validation: 'md5'
}, function(error, file) {

    if (error) {
        sails.log.error(error);
    }

    return res.ok('Image uploaded');
});

是否可以直接上传图像的base64编码字符串,而不必将其转换为文件,然后使用路径上传?

我认为解决方案是使用
file.createWriteStream
功能,该功能由
bucket.upload
函数包装在Google Cloud Node SDK中

我对streams没有什么经验,所以如果这不能马上奏效,请尽量容忍我

首先,我们需要获取base64数据并将其放入流中。为此,我们将包括
库,从base64数据创建一个缓冲区,并将该缓冲区添加到流的末尾

var stream = require('stream');
var bufferStream = new stream.PassThrough();
bufferStream.end(Buffer.from(req.body.base64Image, 'base64'));
更多关于和

然后,我们将通过管道将流传输到由
file.createWriteStream
函数创建的写入流中

var gcs = require('@google-cloud/storage')({
  projectId: 'grape-spaceship-123',
  keyFilename: '/path/to/keyfile.json'
});

//Define bucket.
var myBucket = gcs.bucket('my-bucket');
//Define file & file name.
var file = myBucket.file('my-file.jpg');
//Pipe the 'bufferStream' into a 'file.createWriteStream' method.
bufferStream.pipe(file.createWriteStream({
    metadata: {
      contentType: 'image/jpeg',
      metadata: {
        custom: 'metadata'
      }
    },
    public: true,
    validation: "md5"
  }))
  .on('error', function(err) {})
  .on('finish', function() {
    // The file upload is complete.
  });
有关、和的信息


因此,上述代码的工作方式是定义要将文件放入的bucket,然后定义文件和文件名。我们不在这里设置上传选项。然后,我们将刚刚创建的
bufferStream
变量导入前面讨论过的
文件.createWriteStream
方法。在这些选项中,我们定义了元数据和要实现的其他选项。直接查看以了解它们如何分解
bucket.upload
函数非常有帮助,并建议您也这样做。最后,我们附加了几个事件,用于上传完成和出错的时间。

发布我的答案版本,以响应@krlozadan的上述请求:

// Convert the base64 string back to an image to upload into the Google Cloud Storage bucket
var mimeTypes = require('mimetypes');

var image = req.body.profile.image,
    mimeType = image.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/)[1],
    fileName = req.profile.id + '-original.' + mimeTypes.detectExtension(mimeType),
    base64EncodedImageString = image.replace(/^data:image\/\w+;base64,/, ''),
    imageBuffer = new Buffer(base64EncodedImageString, 'base64');

// Instantiate the GCP Storage instance
var gcs = require('@google-cloud/storage')(),
    bucket = gcs.bucket('my-bucket');

// Upload the image to the bucket
var file = bucket.file('profile-images/' + fileName);

file.save(imageBuffer, {
    metadata: { contentType: mimeType },
    public: true,
    validation: 'md5'
}, function(error) {

    if (error) {
        return res.serverError('Unable to upload the image.');
    }

    return res.ok('Uploaded');
});
这对我来说很好。忽略前几行中的一些附加逻辑,因为它们只与我正在构建的应用程序相关。

:)真是个问题!!已经尝试过,并得到了问题的图像已上传到firebase存储,但没有下载,只是加载程序正在四处移动。。。花时间之后。。。已通过下载成功将图像上载到firebase存储上。。。访问令牌中出现问题

check the screenshot

如果您在右侧底部的文件位置部分签入“创建访问令牌”选项,并且在该选项上不显示任何“访问令牌”,如果您在该选项上手动创建访问令牌,则刷新页面图像将显示。。。所以现在的问题是如何通过代码创建它

只需使用下面的代码创建访问令牌

const uuidv4 = require('uuid/v4');
const uuid = uuidv4();
metadata: { firebaseStorageDownloadTokens: uuid }
下面给出了将映像上载到firebase存储上的存储映像的完整代码

const functions = require('firebase-functions')
var firebase = require('firebase');
var express = require('express');
var bodyParser = require("body-parser");


如果要将字符串保存为Google Cloud Storage中的文件,可以使用以下方法轻松完成:

const{Storage}=require('@googlecloud/Storage');
常量存储=新存储();
const myBucket=storage.bucket('my-bucket');
const file=myBucket.file('my-file.txt');
const contents='这是文件的内容';
然后(()=>console.log('done');

您必须将base64转换为图像缓冲区,然后按如下方式上载,您需要提供
image\u data\u from\u html
变量作为从html事件提取的数据

const base64Text = image_data_from_html.split(';base64,').pop();
const imageBuffer = Buffer.from(base64Text, 'base64');
const contentType = data.image_data.split(';base64,')[0].split(':')[1];
const fileName = 'myimage.png';
const imageUrl = 'https://storage.googleapis.com/bucket-url/some_path/' + fileName;

await admin.storage().bucket().file('some_path/' + fileName).save(imageBuffer, {
    public: true,
    gzip: true,
    metadata: {
        contentType,
        cacheControl: 'public, max-age=31536000',
    }
});

console.log(imageUrl);

我只需要一行代码就可以将base64字符串转移到我的云存储桶中

var decodedImage = new Buffer(poster64, 'base64');
        

// Store Poster to storage
let posterFile = await client.file(decodedImage, `poster_${path}.jpeg`, { path: 'submissions/dev/', isBuffer: true, raw: true });
let posterUpload = await client.upload(posterFile, { metadata: { cacheControl: 'max-age=604800' }, public: true, overwrite: true });
let permalink = posterUpload.permalink
需要注意的是,如果您在Nodejs环境中,您将无法使用atob()

这篇文章的第一个答案向我展示了我的错误!
bucket.upload
包装了
file.createWriteStream
函数,因此您需要将base64文件字符串通过管道传输到
文件中该方法创建的流中。我建议只写文件系统并在上传后取消链接。我认为你删除这些文件不会有问题。如果你愿意的话,我也许可以举个例子。@forrestmid非常希望你能举个例子,说明如何实现
文件.createWriteStream
直接上传。谢谢谢谢你发布这个!实际上,我做了一些类似的事情,除了,我使用了API,它是
createWriteStream
@Nag的总称,绝对有效!我通读了那个API,但并没有注意到它的操作与您所寻找的相匹配。很高兴你能找到答案。@Nag你到底是怎么做到的?你有我们可以看的源代码吗??我一直在为此奋斗。我正在尝试从Firebase云将base64编码的图像字符串上载到Firebase存储Functions@krlozadan请看下面我的答案。我不确定云存储和Firebase存储之间有什么区别,因此我无法对Firebase发表评论。希望这能有所帮助。请注意,缓冲区构造函数因安全问题而被弃用。我们应该改用
Buffer.from(req.body.base64Image,'base64')
。问题是关于上传“base64编码图像”。这不起作用。如果将
contents
设置为此,则此选项适用于base64字符串,其中
data
是base64编码文件:
Buffer.from(data.replace(/^data:image\/(png | gif | jpeg);base64,/,'','base64')
不确定从何处获得
isBuffer:true,raw:true
我在SDK中没有看到这些内容。值得指出的是,如果base64编码字符串实际上是一个dataURL(请参见:),就像从c生成的一样
var decodedImage = new Buffer(poster64, 'base64');
        

// Store Poster to storage
let posterFile = await client.file(decodedImage, `poster_${path}.jpeg`, { path: 'submissions/dev/', isBuffer: true, raw: true });
let posterUpload = await client.upload(posterFile, { metadata: { cacheControl: 'max-age=604800' }, public: true, overwrite: true });
let permalink = posterUpload.permalink