How to upload images to firebase without using an HTML form? - javascript

How do I upload images to firebase without an HTML form, I need to use code only.
I have tried some ways myself but the files fail to preview they're corrupted I guess.
I'm developing my App in React and I need a way to upload images to firebase without an HTML form
I tried:
await uploadBytes(storageRef, '../images/image.jpg')
I also tried:
const metadata ={ contentType:'image/jpeg' }
and also
const metadata ={
contentType:'image/svg+xml'
}
await uploadBytes(storageRef, '../images/image.jpg', metadata)

There is no way to upload a file to Cloud Storage for Firebase with just a local path as you do here uploadBytes(storageRef, '../images/image.jpg').
If you pass a string as the second argument, you will have to call uploadString and the second argument has to be the base64 encoded data that you want to upload.
If you want to upload a file based on its path, you will have to either create a File reference to that file, or read its data into a Blob and then pass that to uploadBytes.
All of these are covered in the Firebase documentation on uploading data, so I recommend keeping that handy.

use the Firebase SDK for Cloud Storage and the FileReader API in JavaScript.
import { getStorage, ref, uploadBytes } from "firebase/storage";
const storage = getStorage();
const handleFileUpload = (file) => {
const storageRef = ref(storage, "images/" + file.name);
const metadata = {
contentType: file.type,
};
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = async (event) => {
const buffer = event.target.result;
await uploadBytes(storageRef, buffer, metadata);
};
};

Related

Upload files to firebase storage via function

I am trying to allow ability for user to select file and pass to firebase function to store in storage.
I am uploading file in react client like following:
const formData = new FormData();
formData.append("myFile", aFile);
const aRequesObject= {
method: "POST",
body: formData,
};
const response = await fetch(aUrl, aRequesObject);
Then I have a serverless function like following where i want to save this file to cloud storage.
import firebase from "firebase";
import "firebase/storage";
import { config } from "./Config";
firebase.initializeApp(config);
const file = request.body.myFile;
const ref = firebase.storage().ref().child(file.name);
ref.put(file).then(() => {
console.log("Uploaded file", file.name);
}); */
I have tried several variations from firebase documentation. All the examples i have found are uploading directly to storage from client as opposed to passing file to function and extracting from the request and then saving to storage. I am looking for a simple example of this or a link to where someone has done this scenario.

AWS S3 Image Upload Error: Unsupported Body Payload Object

I try to upload a local image to an s3 bucket and keep getting
Error: Unsupported body payload object
The image can be jpg, jpeg, or png. I've read that images can only be uploaded to s3 as base64 so I read the file as a base64 string using readAsDataURL, and then create a Buffer with it.
const reader = new FileReader()
reader.readAsDataURL(file)
const base64str = reader.result.replace(/^data:image\/\w+;base64,/, "");
const fileContent = Buffer.from(base64str,'base64')
The above code is executed on the react frontend where fileContent is set to a variable through a hook, and that variable gets PUT-ed to my server with
static uploadImage = (id, fileContent) => {
return axios.put(ROOT_URL + "/images/" + id, fileContent);
}
Then its uploaded with
await s3.upload({
Bucket: BUCKET_NAME,
Key: KEY,
Body: fileContent,
ContentType: TYPE,
}).promise();
I have tried many different solutions I've found on this website, and still receive the error. Not sure what I am missing.
EDIT: Here is one of the threads that I found helpful, but did not fix the error.
Uploading base64 encoded Image to Amazon S3 via Node.js
Not sure where you read that images must be base64, but you can simply read the file content with something like fs and upload it to S3 as it is.
// Read content from the file
const fileContent = fs.readFileSync(fileName);
// Setting up S3 upload parameters
const params = {
Bucket: BUCKET_NAME,
Key: 'cat.jpg', // File name you want to save as in S3
Body: fileContent
};
// Uploading files to the bucket
await s3.upload(params).promise();

Storing and retrieving a base64 encoded string in Firebase storage

I have a Base64 encoded string (this is AES encrypted string).
I am trying to store it in Firebase Storage and then download it from it.
I have tried multiple options e.g
pathReference.putString(data, 'base64')
This does not retain the the base64 string in storage but converts it into integers. I have also tried providing a {contentType: "application/Base64"} but putString doesn't seem to work.
I then tried making it a blob
blob = new Blob([data], {type: "application/Base64"})
await pathReference.put(blob)
With this I am able to get the base64 encoded string in storage (though there are newlines added in string)
When I download it with ES6 fetch I am not getting back the string
const url = await pathReference.getDownloadURL()
const response = await fetch(url)
const data = await response.blob()
Instead getting an error Unhandled promise rejection: URIError: URI error
I am just looking for a very simple upload and download sample for base64 encoded string to firebase storage.
Any help is greatly appreciated.
I was able to make it work, though some firebase / fetch with react-native behavior is still unclear.
To upload a base64 encoded string to firebase storage I used the following snippet.
Here "data" is already a Base64 encoded string.
const pathReference = storage.ref(myFirebaseStorageLocation)
const blob = new Blob([data], {type: "application/Base64"})
await pathReference.put(blob)
I verified the contents in Firebase storage and downloaded the file manually which also looked fine.
Then to download under a React Native, Expo project there were several roadblocks but what finally worked was this
I had to add a btoa() function in global namespace.
Used the following code to download and then read it back as a Base64 string (which was surprisingly hard to get to)
Code to download the file and read back as Base64 string.
const fetchAsBlob = url => fetch(url)
.then(response => response.blob());
const convertBlobToBase64 = blob => new Promise((resolve, reject) => {
const reader = new FileReader;
reader.onerror = reject;
reader.onload = () => {
resolve(reader.result);
};
reader.readAsDataURL(blob);
});
const url = await pathReference.getDownloadURL()
const blob = await fetchAsBlob(url)
const doubleBase64EncodedFile = await convertBlobToBase64(blob)
const doubleEncodedBase64String = doubleBase64EncodedFile.split(',')[1]
const myBase64 = Base64.atob(doubleEncodedBase64String)
The caveat was that the FileReader reads the content and encodes it again into Base64 (so there is double encoding). I had to use the Base64.atob() to get back my original Base64 encoded string.
Again this may be unique to the situation where there is fetch being called under a React Native Expo project, both of which have some additional quirks when it comes to handling blobs or Base64.
(PS: I tried using response.blob(), response.buffer() and tried everything including libs to convert Blobs to Base64 strings but ran into one or the other issue, I also tried using Expo FileSystem, download file locally and read using FileSystem.readAsStringAsync, but it ran into native issues with iOS. tl;dr; the above solution worked but if someone can provide any explanation or clarity on all other attempts or a better solution then it will be greatly appreciated.
Also unclear is why firebase storage putString(data, 'base64') does not work.)

Upload image to strapi with external link

What is a proper way to upload an external image via URL into strapi on backend-side?
I had tried to load image with node-fetch and processed it with buffer()/blob()/blob().stream() and then passed it into strapi.plugins['upload'].services.upload.upload(). Also tried to generate FormData in node.js and passed it into upload service but still didn't help.
How to convert image buffer from fetch into suitable type for upload service?
I used axios and it was on client, but you can try in on server too I think.
This worked for me:
Fetch an image and create File instance from it
async getImage(imageUrl, imageName) {
const response = await axios.get(imageUrl, { responseType: 'blob' });
const mimeType = response.headers['content-type'];
const imageFile = new File([response.data], imageName, { type: mimeType });
return imageFile;
}
GraphQL API query
{
query: `
mutation($files: [Upload!]!) {
multipleUpload(files: $files) {
id
}
}
`,
variables: {
files: [
// your files to upload
]
}
}
Then I called this mutation and it worked perfect.
Resources that I used to find this solution:
https://www.freecodecamp.org/news/how-to-manage-file-uploads-in-graphql-mutations-using-apollo-graphene-b48ed6a6498c/
Client side convert png file stream into file object
https://github.com/jaydenseric/graphql-multipart-request-spec

Create File or Blob from local path in Javascript

I have extensively and systematically searched for an answer in stack overflow but haven't been able to find one that fits my needs.
I am trying to upload a number of files to Firebase Storage, which requires a File or Blob object.
var file = ... // use the Blob or File API
ref.put(file).then(function(snapshot) {
console.log('Uploaded a blob or file!');
});
I have a folder in my project with all the files I want to upload, and I'm trying to create such objects with their paths. However, none of my attempts have worked.
I tried importing the file:
let file = require('./Images/imagename.jpg');
and I researched using 'fs', the File API and other options, but none seem to have a way for me to get the file into an object using only the path.
In short: is there any simple way to get the object from a local path?
Here is how you can upload a file from the drive to Firebase Storage:
let bucket = admin.storage().bucket();
let uploadRes = await bucket.upload(filePath, options);
You can find a description of the option in the google cloud storage docs.
You will most likely create a key in the google cloud console with permissions and export the file as a json. You will find this in the Google Cloud Platform console -> IAM & admin -> Service accounts -> Create service account (create it with a key). Once you exported the json, set the environment variable like this:
export GOOGLE_APPLICATION_CREDENTIALS='./the_exported_file.json'
PLEASE STORE THIS FILE SECURELY ON YOUR SERVER AS IT HAS READ AND WRITE ACCESS!
Below is a full example of an upload function that also saves the file under it's hash name.
<!-- language: typescript -->
import admin from "firebase-admin";
import path from 'path'
const sha256File = require('sha256-file');
const firebaseConfig = {
apiKey: "...",
authDomain: "abc.firebaseapp.com",
databaseURL: "https://abc.firebaseio.com",
projectId: "abc",
storageBucket: "abc.appspot.com",
messagingSenderId: "123",
appId: "1:123:web:xxx",
measurementId: "G-XXX"
};
admin.initializeApp(firebaseConfig);
async function uploadFile(filePath: string, uploadFolder: string, contentType: string, hash: string | undefined = undefined,)
: Promise<string> {
if (!hash) {
hash = await sha256File(filePath);
}
let bucket = admin.storage().bucket();
const ext = path.extname(filePath);
const uploadPath = uploadFolder + hash + ext;
const options = {destination: uploadPath};
console.debug("starting upload");
let uploadRes = await bucket.upload(filePath, options);
console.debug("finished upload");
let newMetadata = {
contentType: contentType
};
if(uploadRes) {
let file = uploadRes[0];
file.setMetadata(newMetadata).then(() => {
// Updated metadata for 'images/forest.jpg' is returned in the Promise
}).catch(function (error) {
console.error(error)
});
}
return uploadPath;
}
This should work in recent versions of Node.js:
import fs from "fs";
import { Blob } from "buffer";
let buffer = fs.readFileSync("./your_file_name");
let blob = new Blob([buffer]);
First of all tell me that which technology you're using for front-end.
If you are using angular than you just need to get $event every time like change event.
than you need to create FormData object.
Pass that object into node and node side use multer for storing the file.
if you need the demo let me know I can help you....

Categories

Resources