Ionic 4 : Recording Audio and Send to Server (File has been corrupted) - angular6

I would like to record the audio file in mobile application(iOS & Android) and tranfer to server as a formData in ionic 4. I have used the "cordova-plugin-media" to capture the audio using below logics
if (this.platform.is('ios')) {
this.filePaths = this.file.documentsDirectory;
this.fileExtension = '.m4a';
} else if (this.platform.is('android')) {
this.filePaths = this.file.externalDataDirectory;
this.fileExtension = '.3gp';
}
this.fileName = 'recording'+new Date().getHours()+new Date().getMinutes()+new Date().getSeconds()+this.fileExtension;
if(this.filePaths) {
this.file.createFile(this.filePaths,this.fileName,true).then((entry:FileEntry)=> {
this.audio = this.media.create(entry.toInternalURL());
this.audio.startRecord();
});
}
Even I have tried to create the media directly without "File Creation"
I can record and play the audio, but If I am trying to send this file
to server using below logics It won't send properly(corrupted data)
and also web application unable to play .m4a extensions
.
Please correct me If I am doing anything wrong in my code
Upload logic:
let formData:FormData = new FormData();
formData.append('recordID' , feedbackID);
that.file.readAsDataURL(filePath,file.name).then((data)=>{
const audioBlob = new Blob([data], { type: file.type });
formData.append('files', audioBlob, file.name);
that.uploadFormData(formData,feedbackID); //POST Logics -
})
;
I have used the soultion as suggested by Ankush and it works fine.
Used readAsArrayBuffer instead of readAsDataURL.
The .m4a format has supported both ios and android. Also I can
download the the same file from web application.

I am using below code to upload the image to the server. I assume that only a few modifications will be required in this code to transfer media instead of the image file.
private uploadPicture(imagePath: string, apiUrl: string): Observable<ApiResponse<ImageUploadResponseModel>> {
return this.convertFileFromFilePathToBlob(imagePath).pipe(
switchMap(item => this.convertBlobToFormData(item)),
switchMap(formData => this.postImageToServer(formData, apiUrl))
);
}
Rest functions used in above code:
private postImageToServer(formData: FormData, apiUrl: string): Observable<ApiResponse<ImageUploadResponseModel>> {
const requestHeaders = new HttpHeaders({ enctype: 'multipart/form-data' });
return this.http.post<ApiResponse<ImageUploadResponseModel>>(apiUrl, formData, { headers: requestHeaders });
}
private convertBlobToFormData(blob: Blob): Observable<FormData> {
return new Observable<FormData>(subscriber => {
// A Blob() is almost a File() - it's just missing the two properties below which we will add
// tslint:disable-next-line: no-string-literal
blob['lastModifiedDate'] = new Date();
// tslint:disable-next-line: no-string-literal
blob['name'] = 'sample.jpeg';
const formData = new FormData();
formData.append('file', blob as Blob, 'sample.jpeg');
subscriber.next(formData);
subscriber.complete();
});
}
private convertFileFromFilePathToBlob(imagePath: string): Observable<Blob> {
return new Observable<Blob>(subscriber => {
const directoryPath = imagePath.substr(0, imagePath.lastIndexOf('/'));
let fileName = imagePath.split('/').pop();
fileName = fileName.split('?')[0];
this.file.readAsArrayBuffer(directoryPath, fileName).then(fileEntry => {
const imgBlob: any = new Blob([fileEntry], { type: 'image/jpeg' });
imgBlob.name = 'sample.jpeg';
subscriber.next(imgBlob);
subscriber.complete();
}, () => {
subscriber.error('Some error occured while reading image from the filepath.');
});
});
}

Related

Resize all existing images stored in firebase storage and update the newly resized image url to database via api call [duplicate]

This question already has an answer here:
How can I resize all existing images in firebase storage?
(1 answer)
Closed 9 months ago.
I have requirement to resize new and existing images stored in firebase store. For new image, I enabled firebase's resize image extension. For existing image, how can I resized the image and get the newly resized image url to update back to database via api.
Here is my firebase function to get existing image urls from database. My question is how to resize the image and get the new image url?
const functions = require("firebase-functions");
const axios =require("axios");
async function getAlbums() {
const endpoint = "https://api.mydomain.com/graphql";
const headers = {
"content-type": "application/json",
};
const graphqlQuery = {
"query": `query Albums {
albums {
id
album_cover
}
}`
};
functions.logger.info("Call API");
const response = await axios({
url: endpoint,
method: 'post',
headers: headers,
data: graphqlQuery
});
if(response.errors) {
functions.logger.info("API ERROR : ", response.errors) // errors if any
} else {
return response.data.data.albums;
}
}
exports.manualGenerateResizedImage = functions.https.onRequest(async () => {
const albums = await getAlbums();
functions.logger.info("No. of Album : ", albums.length);
});
I think the below answer from Renaud Tarnec will definitely help you.
If you look at the code of the "Resize Images" extension, you will see that the Cloud Function that underlies the extension is triggered by a onFinalize event, which means:
When a new object (or a new generation of an existing object) is
successfully created in the bucket. This includes copying or rewriting
an existing object.
So, without rewriting/regenerating the existing images the Extension will not be triggered.
However, you could easily write your own Cloud Function that does the same thing but is triggered, for example, by a call to a specific URL (HTTPS cloud Function) or by creating a new document in a temporary Firestore Collection (background triggered CF).
This Cloud Function would execute the following steps:
Get all the files of your bucket, see the getFiles() method of the
Google Cloud Storage Node.js Client API. This method returns a
GetFilesResponse object which is an Array of File instances.
By looping over the array, for each file, check if the file has a
corresponding resized image in the bucket (depending on the way you
configured the Extension, the resized images may be in a specific
folder)
If a file does not have a corresponding resized image, execute the
same business logic of the Extension Cloud Function for this File.
There is an official Cloud Function sample which shows how to create a Cloud Storage triggered Firebase Function that will create resized thumbnails from uploaded images and upload them to the database URL, (see the last lines of index.js file)
Note : If you have a lot of files to treat, you should most probably work by batch, since there is a limit of 9 minutes for Cloud Function execution. Also, depending on the number of images to treat, you may need to increase the timeout value and/or the allocated memory of your Cloud Function, see https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation
In case someone need it. This is how I resized existing image.
const functions = require("firebase-functions");
const axios = require("axios");
const { Storage } = require("#google-cloud/storage");
const storage = new Storage();
// Don't forget to replace with your bucket name
const bucket = storage.bucket("projectid.appspot.com");
async function getAlbums() {
const endpoint = "https://api.mydomain.com/graphql";
const headers = {
"content-type": "application/json",
};
const graphqlQuery = {
query: `query Albums {
albums {
id
album_cover
}
}`,
};
const response = await axios({
url: endpoint,
method: "post",
headers: headers,
data: graphqlQuery,
});
if (response.errors) {
functions.logger.error("API ERROR : ", response.errors); // errors
if any
} else {
return response.data.data.albums;
}
}
function getFileName(url) {
var decodeURI = decodeURIComponent(url);
var index = decodeURI.lastIndexOf("/") + 1;
var filenameWithParam = decodeURI.substr(index);
index = filenameWithParam.lastIndexOf("?");
var filename = filenameWithParam.substr(0, index);
return filename;
}
function getFileNameFromFirestore(url) {
var index = url.lastIndexOf("/") + 1;
var filename = url.substr(index);
return filename;
}
const triggerBucketEvent = async () => {
bucket.getFiles(
{
prefix: "images/albums", // you can add a path prefix
autoPaginate: false,
},
async (err, files) => {
if (err) {
functions.logger.error(err);
return;
}
const albums = await getAlbums();
await Promise.all(
files.map((file) => {
var fileName = getFileNameFromFirestore(file.name);
var result = albums.find((obj) => {
return getFileName(obj.album_cover) === fileName;
});
if (result) {
var file_ext = fileName.substr(
(Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1
);
var newFileName = result.id + "." + file_ext;
// Copy each file on thumbs directory with the different name
file.copy("images/albums/" + newFileName);
} else {
functions.logger.info(file.name, " not found in album list!");
}
})
);
}
);
};
exports.manualGenerateResizedImage = functions.https.onRequest(async () => {
await triggerBucketEvent();
});

How am I able to embed a blob video file from an API call in the HTML and play it within the same HTML page?

I am currently having a few methods in the following where handlePdfBlob handles fileType that are in "pdf" while the rest are for other file types where the blob data will be downloaded using handleBlob method. I would like to have a seperate method for fileType that are in "mp4" where the video is not downloaded but being played in the same HTML page upon clicking on a button. I have look at the HTMLVideoElement but I am not sure how am I able to assign the blob data object that is given in the response body of the API to the HTMLVideoElement "video" tag in the HTML file. What are some suggested ways that I am able to achieve playing the video directly in the HTML page after making the API calling from the HTML page?
downloadSampleFile(apiUrl: string, fileName: string, fileType: string, req: any = {}): void {
const options = createRequestOption(req);
this.http.get<Blob>(apiUrl, { params: options, observe: 'response', responseType: 'blob' as 'json' })
.subscribe(((res: HttpResponse<Blob>) => {
if (fileType.match("pdf")) {
this.handlePdfBlob(res.body!, fileName, fileType);
}
else {
this.handleBlob(res.body!, fileName, fileType);
}
}));
}
private handlePdfBlob(data: Blob, fileName: string, fileType: string): void {
const blob = new Blob([data], { type: 'application/pdf' });
const url = window.URL.createObjectURL(blob);
window.open(url);
}
private handleBlob(data: Blob, fileName: string, fileType: string): void {
const blob = new Blob([data], { type: 'application/octet-stream' });
const url = window.URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.download = fileName + "." + fileType;
anchor.href = url;
anchor.click();
}
I have tried to create a new method for this and return the URL string.
const url = window.URL.createObjectURL(blob);
However, I am not sure why the url is returning undefined in the console.

Forge api translating .fbx to SVF2 doesnt work and translates only to SVF

I am using forge-apis package on Node.js and I want to translate a .fbx file in SVF2. When I do so and load the model, size and GPU memory used is the same as normal translate to SVF and when I check viewer.model.isSVF2() it return false.
const {
DerivativesApi,
JobPayload,
JobPayloadInput,
JobPayloadOutput,
JobSvfOutputPayload} = require('forge-apis');
and
router.post('/jobs', async (req, res, next) => {
const xAdsForce = (req.body.xAdsForce === true);
let job = new JobPayload();
job.input = new JobPayloadInput();
job.input.urn = req.body.objectName;
if(req.body.rootFilename && req.body.compressedUrn) {
job.input.rootFilename = req.body.rootFilename;
job.input.compressedUrn = req.body.compressedUrn;
}
job.output = new JobPayloadOutput([
new JobSvfOutputPayload()
]);
job.output.formats[0].type = 'svf2' ;
job.output.formats[0].views = ['2d', '3d'];
try {
// Submit a translation job using [DerivativesApi](https://github.com/Autodesk-Forge/forge-api-nodejs-client/blob/master/docs/DerivativesApi.md#translate).
const result = await new DerivativesApi().translate(job, { xAdsForce: xAdsForce }, req.oauth_client, req.oauth_token);
res.status(200).end();
} catch(err) {
next(err);
}});
How can I handle this problem? Thanks a lot.

Html to Pdf Format Angular

Hello i want to convert from html to pdf format and send it as a file to my backend, so i can save it in my server, i tried using jspdf but its not working
SendMail() {
var doc = new jspdf();
doc.fromHTML('<h1>Hello World!</h1>', 20, 20);
var blob = new Blob([doc.output("blob")], { type: "application/pdf" });
let lruta = 'report/' + 'test';
this.uploaderService.uploadfile(blob, lruta).subscribe(
response => {
this.fetcher = response;
this.blockUI.stop();
}, error => {
this.blockUI.stop();
}
);
}
This is my service UploadFile
uploadfile(cabecera, ruta) {
const formData = new FormData();
formData.append('file', cabecera[0]);
formData.append('ruta', ruta);
return this._http.post(this.apiUrl + this.serviceUrl + 'gestion/uploadrevision', formData);
}
When i replace blob with this.file in my this.uploaderService.uploadfile
it works, but i dont want to download and upload my file
file: any;
onFileChange(event) {
this.file = event.target.files;
}

Why returning value from picked file is null ? Flutter

In my App I'm using image_picker and image_picker_web but it throws No podspec found for 'image_picker_web' in '.symlinks/plugins/image_picker_web/ios'exception when running on iOS.
So I decided not to use it and pick the file like in the accepted solution here How to Pick files and Images for upload with flutter web.
Print for picked file is correct but my method returns null a I guess it returns the variable before it gets assigned a value.
I don't know html so I'm kinda lost here..
What am I doing wrong with returning the picked value?
FileReader reader = FileReader();
InputElement uploadInput = FileUploadInputElement();
Future<Uint8List> pickImage() async {
print('FirebaseImageStorageRepositoryWeb. pickImage() started');
// image_picker_web works on web but creates pod problems on iOS
// Uint8List imageData;
// String fileName;
// await picker.getImage(source: ImageSource.gallery).then((picked) {
// picked.readAsBytes().then((data) {
// imageData = data;
// });
// });
// image_picker // notworking on web...
//html
Uint8List imageData;
InputElement uploadInput = FileUploadInputElement();
uploadInput.click();
uploadInput.onChange.listen((e) {
// read file content as dataURL
final files = uploadInput.files;
if (files.length == 1) {
final file = files[0];
print(
'selected file: type:${file.type},name: ${file.name}, size: ${file.size}');
reader.onLoadEnd.listen((e) {
imageData = reader.result;
// return imageData; // not working
});
reader.onError.listen((fileEvent) {
print('Some Error occured while reading the file');
});
reader.readAsArrayBuffer(file);
}
});
return imageData;
}
Following the answer at Image picker flutter web 1.9 (not the accepted one .. ) I could see what was wrong with the code above..
working:
#override
Future<Uint8List> pickImage() async {
print('FirebaseImageStorageRepositoryWeb.pickImage() started');
final completer = Completer<Uint8List>();
final InputElement input = document.createElement('input');
input
..type = 'file'
..multiple = true
..accept = 'image/*';
input.click();
// onChange doesn't work on mobile safari
input.addEventListener('change', (e) async {
final List<File> files = input.files;
Iterable<Future<Uint8List>> resultsFutures = files.map((file) {
final reader = FileReader();
reader.readAsArrayBuffer(files.first); // .readAsDataUrl(file);
reader.onError.listen((error) => completer.completeError(error));
return reader.onLoad.first.then((_) => reader.result);
});
final results = await Future.wait(resultsFutures);
completer.complete(results.first);
});
// need to append on mobile safari
document.body.append(input);
// input.click(); can be here
final Uint8List image = await completer.future;
input.remove();
return image;
}