Expected full URL but got a child path, use ref instead - javascript

This is related to this thread, but it's a new problem I encountered. I am trying to add an image to a table cell in HTML, and I'm using Firebase Storage in combination with Firebase Database for this. The idea is to get the image from a gs://xxxxxxxx path in the database and use it in the js, but I get this error in the console:
Firebase Storage: Invalid argument in refFromURL at index 0: Expected full URL but got a child path, use ref instead."
So it seems that the url_ul path is not working. If, for example, I introduce the 'gs://xxxxxxxx' instead of url_ul, it works like a charm. And if I read the value url_ul as a text, I get that path. However, it doesn't work if I have that variable in refFromURL('url_ul')
I have the following js code for this:
var rootRef = firebase.database().ref().child("Test");
var storage = firebase.storage();
rootRef.on("child_added", snap => {
var headline = snap.child("headline").val();
var url_ul = snap.child("imageUrl").val();
var storageRef = storage.refFromURL('url_ul').then(function(url) {
var test = url;
document.querySelector('img').src = test;
}).catch(function(error) {});
$("#table_body").append("<tr><td>" + headline + "</td><td><img src='test' alt='' border=3 height=100 width=100></td></tr>");});
where the database looks like this:
So there is a gs://xxxxx path, which, according to Firebase documentation, should work fine:
// Create a reference from a Google Cloud Storage URI
var gsReference = storage.refFromURL('gs://bucket/images/stars.jpg')
Any idea what is wrong here?
To make things more clear:
This line works perfectly fine:
var storageRef = storage.refFromURL("gs://nameofapp.appspot.com/armonii_culturale.png").getDownloadURL().then(function(url) ...
But this one doesn't
var storageRef = storage.refFromURL("url_ul").getDownloadURL().then(function(url) ...
And it's strange because "url_ul" should contain the same value.

Related

Error while trying to get download URL from firebase-storage

I've been trying to get download URL for the an image in my firebase-storage but it keeps throwing an object-does-not-exist error. Any clue what the problem might be? I'm certain the directories match up and there is a profilePhoto.jpg file in the firebase-storage directory.
var storageRef = firebase.storage().ref() //root reference;
var usersRef = storageRef.child('users/');
var userPaths = []; //list of all users
usersRef.listAll()
.then(res => {
for (var i = 0; i < res.prefixes.length; i++) {
userPaths[i] = res.prefixes[i].location.path_;
}
var photoRef = storageRef.child(`${userPaths[0]}/profilePhoto.jpg`);
photoRef.getDownloadURL().then(url => {...});
});
This is the error:
FirebaseError: Firebase Storage: Object 'users/6TitxcYcENhRHXDy0Xatk4ODQKo2/profilePhoto.jpg' does not exist.
I'm with Doug here: I have never seen Firebase give that error message if the file actually exists, so it's more likely that something is wrong in the mapping.
If you can't spot it, maybe you can show a screenshot of the file in the Firebase console, or see if the file shows up when you request a list of files.

Importing string values to pass to an API call in JavaScript

I have a (Twilio) API call which requires credentials accountSid and authToken.
twilio.js
const twilio = require('twilio');
const accountSid = require('./auth/twilio_credentials');
const authToken = require('./auth/twilio_credentials');
console.log('accountSid: ' + accountSid);
console.log('authToken: ' + authToken);
module.exports = new twilio.Twilio(accountSid, authToken);
For security, instead of pasting the values directly into code, I have them in separate file. The credentials are used in the file at the same level as the auth folder
auth/twilio_credentials.js
module.exports = accountSid = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
module.exports = authToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
From the console logs (and using typeof), I was able to verify that the strings are being imported properly to that point, but when I run the code, I get throw new Error('accountSid is required');. However, it works when I paste the values directly into the file.
I feel like this is a wonky JavaScript thing that I'm missing. What's the difference between importing the string value from a different file, versus directly using a hard-coded value?
Try exporting them like this:
exports.accountSid = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
exports.authToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
And then, import them like this:
const {accountSid, authToken} = require("./auth/twilio_credentials");
I will suggest you to check how module.exports and exports work in Node.js here:
What is the purpose of Node.js module.exports and how do you use it?

Firebase Web Storage - upload a file without specifying its name

I'm using Firebase Storage and everything works great.
How can I upload a file without specifying its name?
So the file will get a unique name by Firebase, like they do in the storage.
This is an example of what i'm using now:
firebase.initializeApp(config);
var fileUpload = document.getElementById("uploadFile").files;
var storageRef = firebase.storage().ref(fileUpload[0].name);
var uploadTask = storageRef.put(fileUpload[0]);
And I want to do someting like this:
firebase.initializeApp(config);
var fileUpload = document.getElementById("uploadFile").files;
var storageRef = firebase.storage().ref();
var uploadTask = storageRef.put(fileUpload[0]);
Appreciate any help you can provide. Thanks.
There is no built-in API to generate file names for you in Firebase Storage.
But similar to what the Firebase Database does, you can easily generate a filename client-side that is statistically guaranteed to be unique.
One way to do this would be to generate a UUID, such as with the guid() function from this answer:
var storageRef = firebase.storage().ref(guid());
Note that you'd lose the filename extension here, which is how Firebase Storage determines the file type. So more likely you'll want to determine the filename based on the local filename but then with something before it to make it unique.
var storageRef = firebase.storage().ref(guid()+fileUpload[0].name);
Given this combination, there's a pretty good chance that just prefixing with the local timestamp is unique already:
var storageRef = firebase.storage().ref(Date.now()+fileUpload[0].name);

Parse Cloud Code - Get URL of PFFile

Ok this should be a relatively simple one. Apologies i am an iOS developer usually trying to understand Javascript.
I have a PFFile that is being saves into a PFObject from iOS.
I now need to send the URL of the image to a web service, which i am trying to do using an afterSave method on Cloud Code.
I have the object being fetched, and i can see the file contained within it. But i can't work out how to access the URL value.
I have tried various approaches, and i'm sure it's me not understanding how to access the value on an object, nested in another object. I've listed what i mostly tried below.
I have everything else working apart from this so help would be greatly appreciated.
Thanks
Gareth
var image = request.object.get("userPhoto")
console.log(image);
var imageURL = image.url
var imageURL = image.'url'
var imageURL = image.(url)
var imageURL = image.('url')
console.log(imageURL);
The method for accessing the URL of the Parse.File object is:
var imageURL = image.url();
Per the docs here: https://parse.com/docs/js_guide#files-retrieving

createBlockBlob and commitBlobBlocks create empty files in BlobStorage

I'm developing a web app that can upload large file into the Azure Blob Storage.
As a backend, I am using Windows Azure Mobile Services (the web app will generate contents for mobile devices) in nodeJS.
My client can successfully send chunks of data to the backend, everything looks fine but, at the end, the uploaded file is empty. The data upload has been prepared by following this tutorial: it works perfectly when the file is small enough to be uploaded in a single requests. The process fails when the file needs to be broken in chunks. It uses the ReadableStreamBuffer from the tutorial.
Can somebody help me?
Here the code:
Back-end : createBlobBlockFromStream
[...]
//Get references
var azure = require('azure');
var qs = require('querystring');
var appSettings = require('mobileservice-config').appSettings;
var accountName = appSettings.STORAGE_NAME;
var accountKey = appSettings.STORAGE_KEY;
var host = accountName + '.blob.core.windows.net';
var container = "zips";
//console.log(request.body);
var blobName = request.body.file;
var blobExt = request.body.ext;
var blockId = request.body.blockId;
var data = new Buffer(request.body.data, "base64");
var stream = new ReadableStreamBuffer(data);
var streamLen = stream.size();
var blobFull = blobName+"."+blobExt;
console.log("BlobFull: "+blobFull+"; id: "+blockId+"; len: "+streamLen+"; "+stream);
var blobService = azure.createBlobService(accountName, accountKey, host);
//console.log("blockId: "+blockId+"; container: "+container+";\nblobFull: "+blobFull+"streamLen: "+streamLen);
blobService.createBlobBlockFromStream(blockId, container, blobFull, stream, streamLen,
function(error, response){
if(error){
request.respond(statusCodes.INTERNAL_SERVER_ERROR, error);
} else {
request.respond(statusCodes.OK, {message : "block created"});
}
});
[...]
Back-end: commitBlobBlock
[...]
var azure = require('azure');
var qs = require('querystring');
var appSettings = require('mobileservice-config').appSettings;
var accountName = appSettings.STORAGE_NAME;
var accountKey = appSettings.STORAGE_KEY;
var host = accountName + '.blob.core.windows.net';
var container = "zips";
var blobName = request.body.file;
var blobExt = request.body.ext;
var blobFull = blobName+"."+blobExt;
var blockIdList = request.body.blockList;
console.log("blobFull: "+blobFull+"; blockIdList: "+JSON.stringify(blockIdList));
var blobService = azure.createBlobService(accountName, accountKey, host);
blobService.commitBlobBlocks(container, blobFull, blockIdList, function(error, result){
if(error){
request.respond(statusCodes.INTERNAL_SERVER_ERROR, error);
} else {
request.respond(statusCodes.OK, result);
blobService.listBlobBlocks(container, blobFull)
}
});
[...]
The second method returns the correct list of blockId, so I think that the second part of the process works fine. I think that it is the first method that fails to write the data inside the block, as if it creates some empty blocks.
In the client-side, I read the file as an ArrayBuffer, by using the FileReader JS API.
Then I convert it in a Base4 encoded string by using the following code. This approach works perfectly if I create the blob in a single call, good for small files.
[...]
//data contains the ArrayBuffer read by the FileReader API
var requestData = new Uint8Array(data);
var binary = "";
for (var i = 0; i < requestData.length; i++) {
binary += String.fromCharCode( requestData[ i ] );
}
[...]
Any idea?
Thank you,
Ric
Which version of the Azure Storage Node.js SDK are you using? It looks like you might be using an older version; if so I would recommend upgrading to the latest (0.3.0 as of this writing). We’ve improved many areas with the new library, including blob upload; you might be hitting a bug that has already been fixed. Note that there may be breaking changes between versions.
Download the latest Node.js Module (code is also on Github)
https://www.npmjs.org/package/azure-storage
Read our blog post: Microsoft Azure Storage Client Module for Node.js v. 0.2.0 http://blogs.msdn.com/b/windowsazurestorage/archive/2014/06/26/microsoft-azure-storage-client-module-for-node-js-v-0-2-0.aspx
If that’s not the issue, can you check a Fiddler trace (or equivalent) to see if the raw data blocks are being sent to the service?
Not too sure if your still suffering from this problem but i was experiencing the exact same thing and came across this looking for a solution. Well i found one and though id share.
My problem was not with how i push the block but in how i committed it. My little proxy server had no knowledge of prior commits, it just pushes the data its sent and commits it. Trouble is i wasn't providing the commit message with the previously committed blocks so it was overwriting them with the current commit each time.
So my solution:
var opts = {
UncommittedBlocks: [IdOfJustCommitedBlock],
CommittedBlocks: [IdsOfPreviouslyCommittedBlocks]
}
blobService.commitBlobBlocks('containerName', 'blobName', opts, function(e, r){});
For me the bit that broke everything was the format of the opts object. I wasn't providing an array of previously committed block names. Its also worth noting that i had to base64 decode the existing block names as:
blobService.listBlobBlocks('containerName', 'fileName', 'type IE committed', fn)
Returns an object for each block with the name being base64 encoded.
Just for completeness here's how i push my blocks, req is from the express route:
var blobId = blobService.getBlockId('blobName', 'lengthOfPreviouslyCommittedArray + 1 as Int');
var length = req.headers['content-length'];
blobService.createBlobBlockFromStream(blobId, 'containerName', 'blobName', req, length, fn);
Also with the upload i had a strange issue where the content-length header caused it to break and so had to delete it from the req.headers object.
Hope this helps and is detailed enough.

Categories