How to extract the base64 from an image in Angular NGX Dropzone - angularjs

Hey guys I am using NGX Dropzone and I notice when I drag an image into the viewer it is in base64, but when I try to read the console.log(event.addedFiles); I have no information being passed to me with the base64 value. Here's an example of what I get back
[File]
0: File
lastModified: 1625149167659
lastModifiedDate: Thu Jul 01 2021 10:19:27 GMT-0400 (Eastern Daylight Time) {}
name: "210534431_764639924207804_238792847075232344_n.jpeg"
size: 101133
type: "image/jpeg"
webkitRelativePath: ""
__proto__: File
length: 1
__proto__: Array(0)
I have another piece of code which I have been using that transforms a URL into a base64 string. But thats useless to me since the URL can also be shared and opened by anyone from anywhere. However my local image in my computer is only available to me, unless I transform it into base64 which is a string I can save in a database.
This is the script
imageToShow: any;
onURLinserted() {
this.getImage(this.thumb.name).subscribe(data => {
this.createImageFromBlob(data);
}, error => {
console.log("Error occured",error);
});
console.log("Data: ", this.thumb.name);
}
getImage(imageUrl: string): Observable<Blob> {
return this.http
.get<Blob>(imageUrl, { observe: 'body', responseType: 'blob' as 'json' })
}
createImageFromBlob(image: Blob) {
let reader = new FileReader(); //you need file reader for read blob data to base64 image data.
reader.addEventListener("load", () => {
this.imageToShow = reader.result; // here is the result you got from reader which I use to view the image
this.selectedRowData.photo = reader.result; // this is my ngModel read by my HTML input fields
}, false);
if (image) {
reader.readAsDataURL(image);
}
}
//In my HTML code
<img [src]="imageToShow" alt="">
All I am really trying to do is extract the base64 information from the image dragged in there into imageToShow either by using this code if it helps or something similar OR maybe the cdk drag an drop already has a prop that I dont know about
How do I know that the base64 is even available? When I drag an image in it, and I inspect it in the dev tool I can see the src="data:image/jpeg;base64,random stuff..."
Wish I could put some test code here but I will need the dropzone library for it

Looks like ngx-dropzone does not have a prop that provides bas64String.
You can use readAsDataURL to get base64String. The readAsDataURL is used to read the contents of the Blob or File. When the loadend is triggered. At that time, the result attribute contains the data as a data: URL representing the file's data as a base64 encoded string.
The below code worked for me.
html file
<div class="custom-dropzone" ngx-dropzone [accept]="'image/jpeg,image/jpg,image/png,image/gif'"
(change)="onSelect($event)">
<ngx-dropzone-label>
<div>
<h2>Upload photo</h2>
</div>
</ngx-dropzone-label>
<ngx-dropzone-image-preview ngProjectAs="ngx-dropzone-preview" *ngFor="let f of files" [file]="f"
[removable]="true" (removed)="onRemove(f)">
</ngx-dropzone-image-preview>
</div>
.ts file
onSelect(event) {
this.files.push(...event.addedFiles);
if (this.files && this.files[0]) {
for (let i = 0; i < this.files.length; i++) {
this.fileToBase64(this.files[i])
.then(result=>{
const base64String = result.replace('data:', '')
.replace(/^.+,/, ''); // To remove data url part
this.postMultimedias.push({ name:this.files[i].name,content:
base64String});//postMultimedias is a array which holds image name and bas64String
});
}
}
}
fileToBase64 = (file:File):Promise<string> => {
return new Promise<string> ((resolve,reject)=> {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result.toString());
reader.onerror = error => reject(error);
})
}
onRemove(event) {
let position = this.files.indexOf(event);
this.postMultimedias.splice(position, 1);
this.files.splice(position, 1);
}

Related

React-Flask download excel file with button click

I'm trying to download an excel file with the click of a button in my web application. I can see the data come across from my api request, but when I download the file and try to open it I either get a:
"We found a problem with some content in ... Do you want us to try to recover as much as possible" YES => "This file is corrupt and cannot be opened"
or
"... the file format or file extension is not valid. Verify that theh file has not been corrupted..."
If I open the original file saved it works fine so it's not the file. I think the problem is somewhere in the React Code.
I've looked at a lot of other questions on Stack Overflow about this same topic but none of the answers seem to be working for me.
React
React.useEffect(() => {
if (template && downloadBtn.current != null) {
axios
.get<Blob>(
`/template`,
{ params: { filename: template } }
// responseType: 'blob' or "arraybuffer" don't work for me
)
.then((resp) => {
console.log(resp.data);
var blob = new Blob([resp.data], {
type: resp.headers['content-type'] // tried keeping and removing this
}); // removing this assuming resp.data is already a blob didn't work
console.log(blob); // PK ... b���C���h����ؒ )���G+N�
const url = window.URL.createObjectURL(blob);
console.log(url); // blob:http://localhost:3000/29fd5f64-da6a-4b9c-b4a4-76cce1d691c8
if (downloadBtn.current != null) {
downloadBtn.current.download = template;
downloadBtn.current.href = url;
}
});
}
}, [template, downloadBtn.current]);
Flask
#app.route('/template', methods=['GET'])
def template():
filename = getRouteData(['filename']) # helper function I wrote to get request.body data
print(os.path.join(
app.config['templates_folder'], filename), file=sys.stderr)
return send_file(os.path.join(app.config['templates_folder'], filename))
# adding as_attachment=True doesn't work for me either
# file path is correct

Using TinyMCE uploading images to a backend

I am trying to use the rich text editor TinyMCE for a blog platform I am currently working on.
I am also using React with a Flask backend. A
User should be able to create a blog entry with the editor and also use/ upload images.
I got everything setup but I don't know how to store the images in my backend so you can save a blog with all it's content.
I got this callback function from their documentation but I do not really understand what's happening there and if it is enough to send the file object to my backend and store it in the database.
file_picker_callback: function (cb, value, meta) {
var input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/png , image/jpg");
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
var id = "blobid" + new Date().getTime();
var blobCache =
window.tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(",")[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
/* call the callback and populate the Title field with the file name */
cb(blobInfo.blobUri(), { title: file.name });
};
reader.readAsDataURL(file);
console.log(file);
};
This is the console.log(file) output
File {name: "wlogLogo.png", lastModified: 1590578382000, webkitRelativePath: "", size: 4591, type: "image/png", …}

upload image to S3 presigned url using react-native-image-picker and axios

I am trying to get an presigned url image upload working correctly. Currently the upload succeeds when selecting an image from the IOS simulator, however when I actually try to view the file it seems the file is corrupted and will not open as an image. I suspect it has something to do with my FormData but not sure.
export async function receiptUpload(file) {
const date = new Date();
const headers = await getAWSHeaders();
const presignUrl = await request.post(
urls.fileUpload.presignUpload,
{file_name: `${date.getTime()}.jpg`},
{headers}
)
.then(res => res.data);
const formData = new FormData();
formData.append('file', {
name: `${date.getTime()}.jpg`,
uri: file.uri,
type: file.type
});
const fileUpload = presignUrl.presignUrl && await request.put(
presignUrl.presignUrl,
formData
)
.then(res => res.status === 200);
}
I have tried from other fixes to change the file uri like so...
Platform.OS === 'android' ? file.uri : file.uri.replace('file://', '');
however this does not seem to work either.
I did this just recently in my current project and the following code is a working example for my use case. I didn't need to convert to a blob either though I am uploading to AWS S3 so if you are uploading elsewhere that may be the issue.
export const uploadMedia = async (fileData, s3Data, setUploadProgress = () => {}) => {
let sendData = { ...fileData };
sendData.data.type = sendData.type;
let formData = new FormData();
formData.append('key', s3Data.s3Key);
formData.append('Content-Type', fileData.type);
formData.append('AWSAccessKeyId', s3Data.awsAccessKey);
formData.append('acl', 'public-read');
formData.append('policy', s3Data.s3Policy);
formData.append('signature', s3Data.s3Signature);
formData.append('file', sendData.data);
return axios({
method: 'POST',
url: `https://${s3Data.s3Bucket}.s3.amazonaws.com/`,
data: formData,
onUploadProgress: progressEvent => {
let percentCompleted = Math.floor((progressEvent.loaded * 100) / progressEvent.total)
setUploadProgress(percentCompleted);
}
})
}
I would first check to see where the issue is occurring. After uploading can you view it on whatever storage service you are trying to upload it to. If so it's something on React Native side. If it doesn't ever get uploaded to the location you know its an error in your upload process. Might help you track the exact location of the error.
I had to do this recently for a project. I believe the data is a base64 string when coming directly from the file input. So the issue is your are uploading a base64 string not the image by simply passing the data field. I had to process it before uploading to the signed URL with the following method.
private dataUriToBlob(dataUri) {
const binary = atob(dataUri.split(',')[1]);
const array = [];
for (let i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], { type: 'image/jpeg' });
}
This answer fixed it for me: How can I upload image directly on Amazon S3 in React Native?
I had tried uploading with axios and fetch with FormData. The download went through but the image file was not readable, even when downloaded to my Mac from the S3 console:
The file "yourfile.jpg" could not be opened. It may be damaged or use a file format that Preview doesn’t recognize.
Only after trying to upload with XHR with the correct Content-Type header did it work. Your signedUrl should be correct as well, which seems to be the case if the download goes through.

Using GridFS-Stream to send image file to Front-End React.js through Axios - Converting chunk to string base64

So I've successfully downloaded my image file to my MongoDB using Multer and Multer-Gridfs-Storage, but I'm having trouble retrieving it.
When I tried to retrieve the data using GridFS-Stream, it came back like this previous question:
GridFS : How to display the result of readstream.pipe(res) in an <img/> tag?
When I use this code, what's sent to my Front-End is only the first chunk in the collection, but it's actually usable.
const readstream = gfs.createReadStream({ filename: files[0].filename });
readstream.on('data', (chunk) => {
res.send({ image: chunk.toString('base64') })
})
How am I able to get back all of the chunks? Should I give up and start using GridFSBucket?
I ended up trying this and it work!
let data = ''
readstream.on('data', (chunk) => {
data += chunk.toString('base64')
})
readstream.on('end', () => {
res.send(data)
})

How to save WAV Blob to MongoDB, retrieve and serve correctly with Node?

I've found many posts dealing with saving binary files using the Mongoose Buffer SchemaType. However, most of them deal with image files, and I haven't been able to get them to work with a WAV audio file.
I'm using Recorder.js to save audio recordings from the built-in microphone. I use Recorder.js' exportWAV function to get a BLOB from the finished recording, then read the blob with FileReader and send it to the Node/Express backend where it is then saved to the DB. I've checked using the Mongo CLI and there is data being saved to the relevant field (starting with BinData(0,"UklGR.lotsofdatahere..="). When I try to get the recording by sentence id, the server responds with an appropriately-MIME-typed .wav file that is unplayable.
It seems that I'm missing something in the way that the files are encoded and decoded for storage in MongoDB. When reading the blob spit out by Recorder.js, it looks like it's already base64 encoded. So that's why I tried loading it as a base64 Buffer before saving to Mongo, and then decoding from a base64 buffer on output. What am I missing here? How can I fix these encoding issues? Thanks!
Note: I don't necessarily need GridFS because these files are well under 16MB. Although, if it's a lot faster to stream files from GridFS, maybe I should switch to that solution. However, I'd like to figure out what's wrong with this approach first.
Here's the relevant code from the Angular frontend:
$scope.start = function() {
$scope.rec.record();
}
$scope.export = function() {
$scope.rec.stop();
$scope.rec.exportWAV(function blobCallback(blob) {
$scope.rec.clear();
var reader = new FileReader();
reader.onload = function(event) {
$.ajax({
type: 'POST',
url: '/saveRecording',
data: {
audio: event.target.result,
text: $scope.text,
timestamp: new Date()
}
}).done(function(data) {
console.log(data);
});
}
reader.readAsDataURL(blob);
});
}
The Express routes:
router.post('/saveRecording', function(request, response, next) {
var sentence = new Sentence();
sentence.audio = new Buffer(request.body.audio, 'base64');
sentence.timestamp = request.body.timestamp;
sentence.text = request.body.text;
// Save sentence to DB with Mongoose
sentence.save(function(error, sentence) {
if (error) {
return next(error);
}
// If no error, send added sentence back to the client.
response.json(sentence);
});
});
router.get('/getRecording/:sentenceId', function(request, response, next) {
Sentence.findById(request.params.sentenceId,
function dbCallback (error, sentence) {
if (error) {
return next(error);
}
if (!sentence) {
return next(new Error('Can\'t find sentence'));
}
var base64Audio = new Buffer(sentence.audio, 'base64');
response.writeHead(200, {
'Content-Type': 'audio/x-wav',
'Content-Length': base64Audio.length
});
response.write(base64Audio);
response.end();
});
});
The Mongoose Schema for Sentences:
var SentenceSchema = new mongoose.Schema({
text: String,
audio: Buffer,
timestamp: Date
});
You can try using GridFs for storing your audio files
check that link

Resources