繁体   English   中英

如何从 Node 中的图像 url 将图像上传到 Google Cloud Storage?

[英]How to upload an image to Google Cloud Storage from an image url in Node?

给定图像 url,我如何将该图像上传到 Google Cloud Storage 以使用 Node.js 进行图像处理?

这是一个2个步骤的过程:

  • 使用requestfetch在本地下载文件。
  • 使用官方上传到 GCL。

     var fs = require('fs'); var gcloud = require('gcloud'); // Authenticating on a per-API-basis. You don't need to do this if you auth on a // global basis (see Authentication section above). var gcs = gcloud.storage({ projectId: 'my-project', keyFilename: '/path/to/keyfile.json' }); // Create a new bucket. gcs.createBucket('my-new-bucket', function(err, bucket) { if (!err) { // "my-new-bucket" was successfully created. } }); // Reference an existing bucket. var bucket = gcs.bucket('my-existing-bucket'); var localReadStream = fs.createReadStream('/photos/zoo/zebra.jpg'); var remoteWriteStream = bucket.file('zebra.jpg').createWriteStream(); localReadStream.pipe(remoteWriteStream) .on('error', function(err) {}) .on('finish', function() { // The file upload is complete. });

如果要将文件保存为 jpeg 图像,则需要编辑 remoteWriteStream 流并添加自定义元数据:

var image = bucket.file('zebra.jpg');
localReadStream.pipe(image.createWriteStream({
    metadata: {
      contentType: 'image/jpeg',
      metadata: {
        custom: 'metadata'
      }
    }
}))

我在挖掘这个文档时发现了这个

为了补充 Yevgen Safronov 的回答,我们可以将请求通过管道传输到写入流中,而无需将图像显式下载到本地文件系统中。

const request = require('request');
const storage = require('@google-cloud/storage')();

function saveToStorage(attachmentUrl, bucketName, objectName) {
  const req = request(attachmentUrl);
  req.pause();
  req.on('response', res => {

    // Don't set up the pipe to the write stream unless the status is ok.
    // See https://stackoverflow.com/a/26163128/2669960 for details.
    if (res.statusCode !== 200) {
      return;
    }

    const writeStream = storage.bucket(bucketName).file(objectName)
      .createWriteStream({

        // Tweak the config options as desired.
        gzip: true,
        public: true,
        metadata: {
          contentType: res.headers['content-type']
        }
      });
    req.pipe(writeStream)
      .on('finish', () => console.log('saved'))
      .on('error', err => {
        writeStream.end();
        console.error(err);
      });

    // Resume only when the pipe is set up.
    req.resume();
  });
  req.on('error', err => console.error(err));
}

处理从远程 url 上传的图像。 参考谷歌文档提供的最新库。 而不是存储图像的缓冲区。 我们可以直接将其发送到存储。

function sendUploadUrlToGCS(req, res, next) {
  if (!req.body.url) {
    return next();
  }

  var gcsname = Date.now() + '_name.jpg';
  var file = bucket.file(gcsname);

  return request({url: <remote-image-url>, encoding: null}, function(err, response, buffer) {
    req.file = {};
    var stream = file.createWriteStream({
      metadata: {
        contentType: response.headers['content-type']
      }
    });

    stream.on('error', function(err) {
       req.file.cloudStorageError = err;
       console.log(err);
       next(err);
    });

    stream.on('finish', function() {
      req.file.cloudStorageObject = gcsname;
      req.file.cloudStoragePublicUrl = getPublicUrl(gcsname);
      next();
    });

    stream.end(buffer);
  });
}

我使用了请求库和存储库来制作它。 下面的代码在 TypeScript 中。 问候

import * as gcs from '@google-cloud/storage';
import {Storage} from '@google-cloud/storage';
import request from 'request';

private _storage: Storage;

constructor() {
    // example of json path: ../../config/google-cloud/google-storage.json
    this._storage = new gcs.Storage({keyFilename: 'JSON Config Path'});
}

public saveFileFromUrl(path: string): Promise<string> {
    return new Promise<any>((resolve, reject) => {
        request({url: path, encoding: null}, (err, res, buffer) => {
            if (res.statusCode !== 200) {
                reject(err);
            }
            const bucketName = 'bucket_name';
            const destination = `bucket location and file name`; // example: 'test/image.jpg'
            const file = this._storage.bucket(bucketName).file(destination);
            // put the image public
            file.save(buffer, {public: true, gzip: true}).then(data => {
                resolve(`${bucketName}/${destination}`)
            }).catch(err => {
                reject(err);
            });
        });
    })
}

将我的解决方案留在这里供想要使用的人使用:

  • Firebase 管理 SDK
  • axios和异步等待
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 * specify an existing bucket.
 * specify any url pointing to an file.
 */
// const bucketName = 'liist-prod-nodejs-backend';
// const url = "https://images.unsplash.com/photo-1601191906024-54b4e490abae?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=800&ixlib=rb-1.2.1&q=80&w=800";

// 1. load required packages
const axios = require('axios');
const crypto = require('crypto');
const httpAdapter = require('axios/lib/adapters/http');

// 2. setup firebase admin SDK + storage bucket
const admin = require('firebase-admin');
const serviceAccount = require('path/to/key.json');
const app = admin.initializeApp({ 
  credential: admin.credential.cert(serviceAccount),
  storageBucket: bucketName
});
const storage = app.storage();
const bucket = storage.bucket(bucketName);

// 3. helper function
function randomToken(size = 20) { // maxsize is 128
  return crypto.randomBytes(64).toString('hex').substr(0, size)
}

// 4. async function to actually upload image from link to firebase storage bucket
async function uploadToStorage(bucket, url) {
  // define filename, folder and access token
  const accessToken = randomToken();
  const bucketName = bucket.name;
  const fileEnding = url.split('.').pop();
  const folder = 'defaultFolder';
  const filename = `myTargetFile`;
  const fullPath = `${folder}/${filename}.${fileEnding}`;
  const fullPathUrlEncoded = `${folder}%2F${filename}.${fileEnding}`;

  // axios request to get file stream
  const axiosResponse = await axios.get(url, { responseType: 'stream', adapter: httpAdapter });
  if (axiosResponse.status !== 200) {
    throw new Error(`axios request to ${url} failed.`);
  } 
  // create file + write stream (=> tweak options if needed)
  const file = bucket.file(fullPath);
  const output = file.createWriteStream({
    gzip: true,
    // if public is true, the file can be found here: `https://storage.googleapis.com/${bucketName}/${fullPath}`;
    public: false, // media token needed, more restricted and secure
    metadata: {
      contentType: axiosResponse.headers['content-type'],
      metadata: {
        firebaseStorageDownloadTokens: accessToken, // define access token
      },
    }
  });
  // wrapp stream around a promise
  // => resolves to public url
  const stream = axiosResponse.data;
  const streamPromise = new Promise(function (resolve, reject) {
    stream.on('data', (chunk) => {
      output.write(new Buffer.from(chunk));
    });
    stream.on('end', () => {
      output.end();
      const publicUrl = `https://firebasestorage.googleapis.com/v0/b/${bucketName}/o/${fullPathUrlEncoded}?alt=media&token=${accessToken}`;
      resolve(publicUrl);
    });
    stream.on('error', (err) => {
      output.end();
      reject(err);
    })
  });
  return await streamPromise;
}

// 4. upload to storage
console.log("uploading file to storage ...");
(async () => {
  const publicUrl = await uploadToStorage(bucket, url);
  console.log(publicUrl);
})(); 

实用程序.js

 // google cloud stoage 
 let fs                = require('fs');
 const { Storage }     = require('@google-cloud/storage');
 var credentials       = require('../../yourProjectCredentials.json');
 const storage         = new Storage({credentials: credentials});

 const bucketName      = 'pictures';

 const uuidV1          = require('uuid/v1');
 var dir               = './images';



/**
 * Store Image to GCP Buket
 * @param { picture }
 * @returns { picture_url }
 */
class ApplicationUtility{

    constructor(){}

    /**
     * Store Image to GCP Buket
     * @param { picture }
     * @returns { picture_url }
     */

    async storeImageTocloud (picture) {

        let fileNamePic = uuidV1();
        let path2 = fileNamePic + "_picture.jpg";
        let path = dir + "/" + path2;
        var bitmap = new Buffer.from(picture, 'base64');
        fs.writeFileSync(path, bitmap, { flag: 'w' }, (err) => {
            if (err)
                throw (err);
        });
        storage
            .bucket(bucketName)
            .upload(path)
            .then(() => console.log(`${fileNamePic} uploaded to 
             ${bucketName}.`))
            .catch(err => { throw (err) });

        let url = `https://storage.googleapis.com/${bucketName}/${path2}`;
        return url;

    }

}


module.exports = ApplicationUtility;

索引.js

  const ImagesStorage              = require('./utility');
  const imagesStorage              = new ImagesStorage();

        //call 
        let picture = body.pic
        let url = await imagesStorage.storeImageTocloud(picture);
        console.log(url)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM