如何从 Node 中的图像 url 将图像上传到 Google Cloud Storage?
Posted
技术标签:
【中文标题】如何从 Node 中的图像 url 将图像上传到 Google Cloud Storage?【英文标题】:How to upload an image to Google Cloud Storage from an image url in Node? 【发布时间】:2016-08-08 06:59:22 【问题描述】:给定一个图片网址,我如何将该图片上传到 Google Cloud Storage 以使用 Node.js 进行图片处理?
【问题讨论】:
【参考方案1】:这是一个两步过程:
使用request或fetch在本地下载文件。用官方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://***.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 管理 SDKaxios
和异步等待
/**
* 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)
【讨论】:
以上是关于如何从 Node 中的图像 url 将图像上传到 Google Cloud Storage?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用自定义 url 和文件夹将图像上传到 cloudinary
如何使用传入的图像 URL 将图像从 iOS 上传到 DropBox?
如何在上传后立即接收 Cloudinary 图像 URL(React JS 和 Node Js)?
如何使用 ios 应用程序将图像上传到 Node.JS 服务器