Reputation: 13257
I have been trying to upload some images to my firebase storage bucket . I have followed this official docs :-
https://firebase.google.com/docs/storage/admin/start
and https://googlecloudplatform.github.io/google-cloud-node/#/docs/storage/latest/storage/bucket
I am able to see the files which are already present in the bucket (these files were stored there using an android app)
But I'm not able to upload local files from nodejs's admin.storage module .
Here is the code :
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://myprojectid.firebaseio.com/" ,
storageBucket : "myprojectid.appspot.com/"
});
bucket = admin.storage().bucket() ;
bucket.upload('./mylocalfile.jpg' , (err , file , response)=>{
console.log(err) ; //always gives me err
console.log(file) ; //gives undefined
}) ;
But bucket.getFiles().then(objects=>console.log(objects)) ;
works perfectly and prints the files present in the root .
How to fix this ?
Here is the error
it prints when console logging err
:
{ ApiError: Not Found
at Object.parseHttpRespMessage (C:\Users\Natesh\Desktop\AttentionPlease_backend\functions\node_modules\firebase-admin\node_modules\@google-cloud\common\src\util.js:156:33)
at Object.handleResp (C:\Users\Natesh\Desktop\AttentionPlease_backend\functions\node_modules\firebase-admin\node_modules\@google-cloud\common\src\util.js:131:18)
at C:\Users\Natesh\Desktop\AttentionPlease_backend\functions\node_modules\firebase-admin\node_modules\@google-cloud\common\src\util.js:465:12
at Request.onResponse [as _callback] (C:\Users\Natesh\Desktop\AttentionPlease_backend\functions\node_modules\firebase-admin\node_modules\retry-request\index.js:179:7)
at Request.self.callback (C:\Users\Natesh\Desktop\AttentionPlease_backend\functions\node_modules\firebase-admin\node_modules\request\request.js:186:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (C:\Users\Natesh\Desktop\AttentionPlease_backend\functions\node_modules\firebase-admin\node_modules\request\request.js:1163:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
code: 404,
errors: [],
response:
IncomingMessage {
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: [Object],
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
ended: true,
endEmitted: true,
reading: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: false,
domain:
Domain {
domain: null,
_events: [Object],
_eventsCount: 1,
_maxListeners: undefined,
members: [] },
_events:
{ end: [Object],
close: [Object],
data: [Function],
error: [Function] },
_eventsCount: 4,
_maxListeners: undefined,
socket:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 9,
connecting: false,
_hadError: false,
_handle: [Object],
_parent: null,
_host: 'www.googleapis.com',
_readableState: [Object],
readable: true,
domain: [Object],
_maxListeners: undefined,
_writableState: [Object],
writable: true,
allowHalfOpen: false,
destroyed: false,
_bytesDispatched: 4047,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [Object],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: null,
read: [Function],
_consuming: true,
_idleTimeout: -1,
_idleNext: null,
_idlePrev: null,
_idleStart: 1307656 },
connection:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 9,
connecting: false,
_hadError: false,
_handle: [Object],
_parent: null,
_host: 'www.googleapis.com',
_readableState: [Object],
readable: true,
domain: [Object],
_maxListeners: undefined,
_writableState: [Object],
writable: true,
allowHalfOpen: false,
destroyed: false,
_bytesDispatched: 4047,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [Object],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: null,
read: [Function],
_consuming: true,
_idleTimeout: -1,
_idleNext: null,
_idlePrev: null,
_idleStart: 1307656 },
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers:
{ 'x-guploader-uploadid': 'AEnB2UqADzuHb4O7UjdBAui1cDWeLNO4s0YuT2krCPoYIHaUrYPjXRH8rBU0mcSi9n7sie11PhALTN2vOKkhykW0apqTbrNB9Q',
vary: 'Origin, X-Origin',
'content-type': 'text/html; charset=UTF-8',
'content-length': '9',
date: 'Sat, 17 Mar 2018 13:24:19 GMT',
server: 'UploadServer',
'alt-svc': 'hq=":443"; ma=2592000; quic=51303431; quic=51303339; quic=51303335,quic=":443"; ma=2592000; v="41,39,35"' },
rawHeaders:
[ 'X-GUploader-UploadID',
'AEnB2UqADzuHb4O7UjdBAui1cDWeLNO4s0YuT2krCPoYIHaUrYPjXRH8rBU0mcSi9n7sie11PhALTN2vOKkhykW0apqTbrNB9Q',
'Vary',
'Origin',
'Vary',
'X-Origin',
'Content-Type',
'text/html; charset=UTF-8',
'Content-Length',
'9',
'Date',
'Sat, 17 Mar 2018 13:24:19 GMT',
'Server',
'UploadServer',
'Alt-Svc',
'hq=":443"; ma=2592000; quic=51303431; quic=51303339; quic=51303335,quic=":443"; ma=2592000; v="41,39,35"' ],
trailers: {},
rawTrailers: [],
upgrade: false,
url: '',
method: null,
statusCode: 404,
statusMessage: 'Not Found',
client:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 9,
connecting: false,
_hadError: false,
_handle: [Object],
_parent: null,
_host: 'www.googleapis.com',
_readableState: [Object],
readable: true,
domain: [Object],
_maxListeners: undefined,
_writableState: [Object],
writable: true,
allowHalfOpen: false,
destroyed: false,
_bytesDispatched: 4047,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [Object],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: null,
read: [Function],
_consuming: true,
_idleTimeout: -1,
_idleNext: null,
_idlePrev: null,
_idleStart: 1307656 },
_consuming: true,
_dumped: false,
req:
ClientRequest {
domain: [Object],
_events: [Object],
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: false,
upgrading: false,
chunkedEncoding: true,
shouldKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedHeader: [Object],
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Object],
connection: [Object],
_header: 'POST /upload/storage/v1/b/myprojectid.appspot.com//o?uploadType=multipart&name=profile HTTP/1.1\r\nUser-Agent: gcloud-node-storage/1.4.0\r\nx-goog-api-client: gl-node/6.11.5 gccl/1.4.0\r\nAuthorization: Bearer ya29.c.<PLACEHOLDER_FOR_SOME_LONG_AUTH_ID>\r\nhost: www.googleapis.com\r\naccept-encoding: gzip, deflate\r\ntransfer-encoding: chunked\r\ncontent-type: multipart/related; boundary=6e012a90-2cb1-4c46-9de5-bb75cb5949ea\r\nConnection: keep-alive\r\n\r\n',
_headers: [Object],
_headerNames: [Object],
_onPendingData: null,
agent: [Object],
socketPath: undefined,
timeout: undefined,
method: 'POST',
path: '/upload/storage/v1/b/myprojectid.appspot.com//o?uploadType=multipart&name=profile',
_ended: true,
parser: null,
timeoutCb: null,
res: [Circular] },
request:
Request {
domain: [Object],
_events: [Object],
_eventsCount: 5,
_maxListeners: undefined,
timeout: 60000,
gzip: true,
forever: true,
pool: [Object],
method: 'POST',
uri: [Object],
headers: [Object],
callback: [Function],
readable: true,
writable: true,
explicitMethod: true,
_qs: [Object],
_auth: [Object],
_oauth: [Object],
_multipart: [Object],
_redirect: [Object],
_tunnel: [Object],
setHeader: [Function],
hasHeader: [Function],
getHeader: [Function],
removeHeader: [Function],
localAddress: undefined,
dests: [],
__isRequestRequest: true,
_callback: [Function: onResponse],
proxy: null,
tunnel: true,
setHost: true,
originalCookieHeader: undefined,
_disableCookies: true,
_jar: undefined,
port: 443,
host: 'www.googleapis.com',
url: [Object],
path: '/upload/storage/v1/b/myprojectid.appspot.com//o?uploadType=multipart&name=profile',
httpModule: [Object],
agentClass: [Object],
agentOptions: [Object],
agent: [Object],
src: [Object],
_started: true,
href: 'https://www.googleapis.com/upload/storage/v1/b/myprojectid.appspot.com//o?uploadType=multipart&name=profile',
req: [Object],
ntick: true,
response: [Circular],
originalHost: 'www.googleapis.com',
originalHostHeaderName: 'host',
responseContent: [Circular],
_destdata: true,
_ended: true,
_callbackCalled: true },
toJSON: [Function: responseToJSON],
caseless: Caseless { dict: [Object] },
read: [Function],
body: 'Not Found' },
message: 'Not Found' }
Upvotes: 2
Views: 2787
Reputation: 2188
Unfortunately the 'upload' function only receive path to local file or url, so it cause some complexity when implement uploading file REST api by cloud functions. I'm guessing it shouldn't be a proper way to upload a file to cloud function server and upload a local file to cloud storage.
Here's what I accomplished to make upload endpoint to firebase (gcloud) storage using multer to get file from the request, then convert it to data and use save function to upload.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');
const multer = require('multer');
const app = express();
const fileUpload = multer();
admin.initializeApp(.......);
/*
* Upload File
**/
app.post('/', fileUpload.single('file'), functions.https.onRequest((req, res) => {
const file = req.file;
const bucket = admin.storage().bucket();
const name = file.originalname;
const bucketFile = bucket.file(name);
bucketFile
.save(new Buffer(file.buffer))
.then(() => {
res.status(200).json({
status: 'success',
data: Object.assign({}, bucketFile.metadata, {
downloadURL: `https://storage.googleapis.com/${bucket.name}/${name}`,
})
});
})
.catch(err => {
res.status(500).json({
status: 'error',
errors: err,
});
});
}));
Here's my POSTMAN screen for test.
Let me know if you need further help.
Upvotes: 6