I'm working on a database with blob data. I made use of deno MySQL to pull the record and want to return it as a base64. In nodejs there's this Buffer.from(<buffer data>, "base64") then to print the base64 value do .toString().
How can I do this using Deno? I've been reading a lot about base64 encoder and some third-party libraries but I can't find anything.
// import mysqlClient from "https://deno.land//x/mysql#v2.10.2/mod.ts"
// mysql configuration :w
// some configuration to connect to mysql
const [{pdf}] = await mysql.query("select pdf from files where ...")
const b64 = atob(pdf); // Invalid Charater
console.log(typeof b64); // String
Tried using nodej and I just have to do Buffer.from(pdf, "base64").toString(); and it returns the correct base64 string
Was able to fix the problem. Seems like the problem was the MySQL plugin. I tried using mysql2 (https://deno.land/x/mysql2#v1.0.6) and it's returning the correct datatype and was able to convert data to base64 with the answers given below.
The Deno standard lib provides functions to encode / decode base64 :
import { decode as base64Decode, encode as base64Encode } from 'https://deno.land/std#0.166.0/encoding/base64.ts'
import { assertEquals } from 'https://deno.land/std#0.166.0/testing/asserts.ts'
const value = 'Hello World!'
console.log('value :', value)
const encodedValue = base64Encode(value)
console.log('encodedValue :', encodedValue)
const decodedValue = new TextDecoder().decode(base64Decode(encodedValue))
console.log('decodedValue :', decodedValue)
assertEquals(decodedValue, value)
Related
I am trying to upload a base64 image to Firebase Storage using React Native Expo. The image I am uploading is taken through the takePictureAsync method in expo-camera library with the following CameraPictureOptions
quality:1
base64:true
exif:false
Next, I store this image in a state variable, named photo, and display it to the user in the app using the Image tag with the uri:
data:image/jpg;base64" + photo.base64
Now when uploading it I first tried the uploadString method as per the firebase storage documentation as below
uploadString(storageRef, photo.base64, 'base64').then((snapshot) => {
console.log('Uploaded a raw string!');
});
But it gave the error message
Unhandled promise rejection: FirebaseError: Firebase Storage: String does not match format 'base64': Invalid character found (storage/invalid-format)
I tried this with other parameters instead of base64 ("data_url", "base64url", and not putting anything in the parameter), but I got essentially the same error for "data_url" and "base64url", and when I don't put anything in the parameter the app crashes. After this I looked online to find a fix, and one issue that that some people brought up to explain this error message was that to decode and encode the base64 string firebase storage used the atob and btoa method respectively, but this did not work in javascript/was deprecated. To that end, the fix that was suggested was adding this to on top of App.js
import {decode, encode} from 'base-64';
if (!global.btoa) {
global.btoa = encode;
}
if (!global.atob)
{
global.atob = decode;
}
However, when I did this the app crashed after the button was pressed that triggered the uploadString method.
After this, I tried using the uploadBytes method as per the documentation. I first tried passing the uri string ("data:image/jpg;base64, base64 data) as input, as below. While this did make the image visible on my firebase storage, the image could not be opened. I think this was because this method expected a File or a Blob as input and the input I gave was a base64 string
uploadBytes(storageRef, uri).then((snapshot) => {
console.log('Uploaded a blob or file!');
});
Next, I looked online for ways to convert the base64 string to a Blob. The first approach I tried was calling the fetch api on uri and the blob function to get the blob and then put that in the uploadBytes function.
const response = await fetch(uri)
const blob = await response.blob()
uploadBytes(storageRef, blob).then((snapshot) => {
console.log('Uploaded a blob or file!');
});
However, I get the following error message, which I was unable to solve.
Error: ENOENT: no such file or directory, open pathToReactNativeApp/http:/LocalIPAddress:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&strict=false&minify=false'
Next, I tried the following to get the blob as suggested here, but this lead the app to crash.
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
console.log(e);
reject(new TypeError("Network request failed"));
};
// on complete
xhr.responseType = "blob";
xhr.open("GET", uri, true);
xhr.send(null);
});
Can someone please guide me on how I can upload this base64 image to firebase storage? Any help would be greatly appreciated!
ImagePicker.launchImageLibraryAsync from expo, will return uri, (no need to include base64 :true)
using that uri generate blob
const response = await fetch(result.uri);
const blob = await response.blob();
using this blob, upload to firebase storage using uploadBytes function
uploadBytes(ref, blob).....
i m using firebase 9 web moduler, will run in all platforms
uploading blob is far batter than using base64 and speedy aswell.
not only images, you can upload videos aswell with this,
I have the following Firebase Cloud Function to get the URL of the file stored in Google Cloud Storage.
const gcs = require('#google-cloud/storage')({keyFilename: 'service-account.json'});
exports.generateFileLink = functions.storage.object().onChange(event => {
const object = event.data;
const filePath = object.name;
const bucket = gcs.bucket(object.bucket);
const file = bucket.file(filePath);
const action = 'read';
const expires = '03-09-2491';
return file.getSignedUrl({action, expires}).then(signedUrls => {
console.log(signedUrls[0])
});
})
This returns the correct URL, but it is over 600 characters long. The URL for the same file as seen on the Firebase web console is less than 200 characters long. Is there any way I can retrieve the URL using firebase-admin or firebase-functions modules to get the shorter URL?
Short answer is that we're working on a firebase-admin Storage client, but it's still a little ways away. For now, signed URLs are the way to go if you need to create a download URL in a function.
Why do you need to generate signed URLs in the function vs using the download URLs provided by Firebase? Is it that you can't retrieve the URL via a client in the function and you need to move it somewhere else?
I’m trying to upload an Sqlite database from IOS Swift 3 to my server using Alamofire 4.0, but having problems converting the sqlite file into the data type required to upload.
The majority of posts / question examples seem to default to uploading images, but I am struggling to find example of uploading sqlite or other file types (for back-up purposes)
I have searched for the basic code and found this so far which looks very reasonable (thanks to following post: Alamofire 4 upload with parameters)
let parameters = ["file_name": "swift_file.jpeg"]
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(UIImageJPEGRepresentation(self.photoImageView.image!, 1)!, withName: "photo_path", fileName: "swift_file.jpeg", mimeType: "image/jpeg")
for (key, value) in parameters {
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
}
}, to:"http://sample.com/upload_img.php")
{ (result) in
switch result
{
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
//Print progress
})
upload.responseJSON { response in
//print response.result
}
case .failure(let encodingError):
//print encodingError.description
}
}
The part I’m struggling with is to append the sqlite file to the upload (multipartFormData.append(………..?) I’ve searched but not found any good reference posts.
Yes, i’m a newbe, but trying hard, any help would be appreciated…..
It's exactly the same as the image example except that the mime type would be application/octet-stream.
Also, you'd probably go ahead and load it directly from the fileURL rather than loading it into a Data first.
As an aside, the parameters in that example don't quite make sense, as it looks redundant with the filename provided in the upload of the image itself. So you'd use whatever parameters your web service requires, if any. If you have no additional parameters, you'd simply omit the for (key, value) { ... } loop entirely.
Finally, obviously replace the file field name with whatever field name your web service is looking for.
// any additional parameters that must be included in the request (if any)
let parameters = ["somekey": "somevalue"]
// database to be uploaded; I'm assuming it's in Documents, but perhaps you have it elsewhere, so build the URL appropriately for where the file is
let filename = "test.sqlite"
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent(filename)
// now initiate request
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(fileURL, withName: "file", fileName: filename, mimeType: "application/octet-stream")
for (key, value) in parameters {
multipartFormData.append(value.data(using: .utf8)!, withName: key)
}
}, to: urlString) { result in
switch result {
case .success(let upload, _, _):
upload
.authenticate(user: self.user, password: self.password) // only needed if you're doing server authentication
.uploadProgress { progress in
print(progress.fractionCompleted)
}
.responseJSON { response in
print("\(response.result.value)")
}
case .failure(let encodingError):
print(encodingError.localizedDescription)
}
}
Unrelated, but if you're ever unsure as to what mime type to use, you can use this routine, which will try to determine mime type from the file extension.
/// Determine mime type on the basis of extension of a file.
///
/// This requires MobileCoreServices framework.
///
/// - parameter url: The file `URL` of the local file for which we are going to determine the mime type.
///
/// - returns: Returns the mime type if successful. Returns application/octet-stream if unable to determine mime type.
func mimeType(for url: URL) -> String {
let pathExtension = url.pathExtension
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as NSString, nil)?.takeRetainedValue() {
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
return mimetype as String
}
}
return "application/octet-stream";
}
I'm setting up this thread in order to clarify, whether firebase storage putString method does or does not work in React-native.
From what I've searched there is currently no way to upload File or Blob types to Firebase Storage using put method.
React Native does not support the File and Blob types, so Firebase Storage uploads will not work in this environment. File downloads do work however.
SOURCE: The Firebase Blog
Thus this call
firebase.storage().ref()
.child(userID)
.put(new File(['this is a small amount of data'], 'sample-text.txt', { type: "text/plain" }), { type: "text/plain" })
.then(p => {console.log(p)})
.catch(p => {console.log(p)})
does not work and ends up with response
code : "storage/unknown" message : "Firebase Storage: An unknown error
occurred, please check the error payload for server response." name :
"FirebaseError" serverResponse : "Multipart body does not contain 2 or
3 parts."
Nevertheless there is another option to upload data to Firebase Storage, using Firebase storage putString method. Which works with plain string. But even if I use this method to upload. I'm getting the same server reponse as before.
firebase.storage()
.ref()
.child(userID)
.putString('string')
.then(p => {console.log(p)})
.catch(p => {console.log(p)});
Bu from what I've learned from this answer. The putString way should work.
What am I doing wrong? The code works fine for me in React. Whenever I paste to React-native. It stops working.
I've just tried react-native-fetch-blob as Ven commented before, and I was able to make it work, try using this snippet from the index file in the example:
1) Before class declaration:
import RNFetchBlob from 'react-native-fetch-blob';
const Blob = RNFetchBlob.polyfill.Blob;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;
2) Inside the storing method:
let filePath = 'YOUR/FILE/PATH';
let fileName = 'file_name.jpg';
let rnfbURI = RNFetchBlob.wrap(filePath);
// create Blob from file path
Blob
.build(rnfbURI, { type : 'image/png;'})
.then((blob) => {
// upload image using Firebase SDK
firebase.storage()
.ref('images')
.child(fileName)
.put(blob, { contentType : 'image/jpg' })
.then((snapshot) => {
console.log('Uploaded', snapshot.totalBytes, 'bytes.');
console.log(snapshot.metadata);
var url = snapshot.metadata.downloadURLs[0];
console.log('File available at', url);
}).catch(function(error) {
console.error('Upload failed:', error);
});
I am trying to send a file via xmlrpc as a base64 encoded string.
QFile sourceFile("/home/alexander/test.jpg");
QByteArray srcRawData = sourceFile.readAll();
QByteArray base64Encoded = srcRawData.toBase64();
std::string strTest(base64Encoded);
xmlrpc_c::paramList sampleAddParms;
sampleAddParms.add(xmlrpc_c::value_string("113957571"));
sampleAddParms.add(xmlrpc_c::value_string(strTest));
sampleAddParms.add(xmlrpc_c::value_string("test.jpg"));
When I send this to my server I get:
Client threw error: RPC response indicates failure. Bad parameter type (ap_adddocument): expected base64 for parameter data, got (Python) .
This is the class definition o xmlrpc_c::value_*
http://xmlrpcpp.sourceforge.net/doc/classXmlRpc_1_1XmlRpcValue.html
I just realized I need to use the xmlrpc_c::value_bytestring() instead. How do I convert a File into a bytestring in C++? I have a ByteArray already.
I am at a loss here..
Looking at your code, it seems that you can use xmlrpc_c::value_string()
Convert your base64 string in to a const char* and try. Following code should work. But still enough detail is not available in your question.
QFile sourceFile("/home/alexander/test.jpg");
QByteArray base64Encoded = sourceFile.readAll().toBase64();
const char* b64Enc = QString::fromLatin1(base64Encoded).toStdString().c_str();
xmlrpc_c::paramList sampleAddParms;
sampleAddParms.add(xmlrpc_c::value_string("113957571"));
sampleAddParms.add(xmlrpc_c::value_string(b64Enc));
sampleAddParms.add(xmlrpc_c::value_string("test.jpg"));