【问题标题】:How to upload an image to Google Cloud Storage from an image url in Node?如何从 Node 中的图像 url 将图像上传到 Google Cloud Storage?
【发布时间】:2016-08-08 06:59:22
【问题描述】:

给定一个图片网址,我如何将该图片上传到 Google Cloud Storage 以使用 Node.js 进行图片处理?

【问题讨论】:

    标签: javascript node.js google-app-engine google-cloud-vision


    【解决方案1】:

    这是一个两步过程:

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

      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'
          }
        }
    }))
    

    我在挖掘 documentation 时发现了这个

    【讨论】:

    • @Yevgen Safronov,谢谢,上传后如何获取响应网址
    • @SandeepJangir 不是 100% 确定,您可以通过连接存储桶的路径和存储桶中的文件路径来构造它,请参阅选项/目标以获取更多详细信息 googlecloudplatform.github.io/google-cloud-node/#/docs/…
    • @SandeepJangir 我推荐使用 google-cloud 包。在 bucket.upload 函数的回调中,您可以对新上传的文件调用 getSignedUrl 以获取存储桶对象的临时 URL。阅读更多here。我不相信自述文件是有关此过程的详细说明,但实际代码中有 cmets 和示例 (IIRC) 可以为您指明正确的方向
    【解决方案2】:

    为了补充 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));
    }
    

    【讨论】:

      【解决方案3】:

      如果处理来自远程 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);
        });
      }
      

      【讨论】:

        【解决方案4】:

        我使用了请求库和存储库来制作它。下面的代码在 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);
                    });
                });
            })
        }
        

        【讨论】:

          【解决方案5】:

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

          • 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);
          })(); 
          

          【讨论】:

            【解决方案6】:

            utility.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;
            

            index.js

              const ImagesStorage              = require('./utility');
              const imagesStorage              = new ImagesStorage();
            
                    //call 
                    let picture = body.pic
                    let url = await imagesStorage.storeImageTocloud(picture);
                    console.log(url)
            

            【讨论】:

              猜你喜欢
              • 2020-11-12
              • 1970-01-01
              • 2017-08-11
              • 1970-01-01
              • 1970-01-01
              • 2021-01-16
              • 1970-01-01
              • 1970-01-01
              • 2020-02-17
              相关资源
              最近更新 更多