Reading binary data from fetch response when ArrayBuffer is not present - react-native

In a react native project i have a HTTP request that returns a binary file that i need to turn into a NodeJS Buffer object. I cannot for the life of me get this to work because arrayBuffer is not implemented in any form in react native and every single thing out there seems to hinge on that being present.
How can i turn a fetch response into a ANYTHING that can be accepted by Buffer? uint8array, anything.
async getFirmwareDownload(firmwareVersion: FirmwareVersion): Promise<Buffer | null> {
try {
const response = await fetch(`${this.getBaseUrl()}${firmwareVersion.url}`);
const blob = await response.blob();
return Buffer.from(blob);
} catch (err) {
console.error(err);
return null;
}
}
I attempted this and while its not throwing errors trying to convert. It is not converting correctly as it is missing several hundred bytes.
async getFirmwareDownload(firmwareVersion: FirmwareVersion): Promise<Buffer | null> {
try {
const response = await fetch(`${this.getBaseUrl()}${firmwareVersion.url}`);
const text = await response.text();
return Buffer.from(text, 'binary');
} catch (err) {
console.error(err);
return null;
}
}

I was finally able to do it in a VERY roundabout way by converting it to base64 data URL and then back into a Buffer. This is probably horribly inefficient but it at least generates the correct size Buffer that matches the file.
blobToBuffer(blob: Blob): Promise<Buffer> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = reject;
reader.onload = () => {
const data = reader.result.slice(reader.result.indexOf('base64,') + 7);
resolve(Buffer.from(data, 'base64'));
};
reader.readAsDataURL(blob);
});
}
I would greatly appreciate any other method of doing this.

Related

multiple SQL queries as one request on sequelize js

Is there a way for sequelize to send multiple queries as one request? Or does sequelize already does that?
Below is my code:
const transaction = await db.transaction();
try {
await Resource.bulkCreate(resourcesTable);
await postContacts(contactsTable, locationsTable);
await postResourceTag(resourceTagTable);
await transaction.commit();
} catch (err) {
logger.error(err);
await transaction.rollback();
throw new HttpError(500, "Database Error"); // placeholder until validation setup
}
const postContacts = async ({ contactsTable, locationsTable }) => {
if (contactsTable?.length) {
await Contact.bulkCreate(contactsTable);
if (locationsTable?.length) {
await Location.bulkCreate(locationsTable);
}
}
};
const postResourceTag = async (resourceTagTable) => {
if (resourceTagTable?.length) {
await Resource_Tag.bulkCreate(resourceTagTable);
}
};
Currently, I believe the bulkCreates are sent as separate requests? I'd prefer if they were sent as one single request like how it'd be if the SQL strings was concatenated and then sent.
Based on this answer you can use an array of promises and then handle them all in one point, is that what you might be looking for?

Netlify server functions unable to handle multipart/form-data

I’m working on a Netlify Function where we take form data for a job application (including a file upload) and pass the data on to a third-party API for use in their system. I was following along with this handy post (thanks!) —
https://www.netlify.com/blog/2021/07/29/how-to-process-multipart-form-data-with-a-netlify-function/
— but seem to have run into a situation where the data in the file is not handled properly (for example, PDFs turn up with blank content, though ASCII metadata appears to be at least partly intact), at least when using the Netlify CLI; I have yet to try on a deploy preview. Writing to a local directory confirms that the issue isn’t with the third party API. Is there something I’m missing when working with these files? Example code below (note that I’ve also attempted to work with the Buffer data, with identical results).
Fetch function to call the Netlify Function:
const data = new FormData(form);
fetch('/.netlify/functions/apply', {
method: 'POST',
body: data,
}).then(res => {
if (!res.ok && res.status !== 406) {
throw new Error('oh no');
}
return res.json();
}).then(data => {
if (Array.isArray(data.missingRequiredFields) && data.missingRequiredFields.length > 0) {
console.log(data);
showMissingFields(data.missingRequiredFields);
} else {
showConfirmationMessage(data.message);
}
}).catch(err => {
showWarningMessage('Something went wrong; please try again.');
}).finally(() => {
submitButton.removeAttribute('disabled');
});
And here’s our Netlify Function:
const Busboy = require("busboy");
const FormData = require("form-data");
const fetch = require("node-fetch");
function parseMultipartForm(event) {
// source: https://www.netlify.com/blog/2021/07/29/how-to-process-multipart-form-data-with-a-netlify-function/
return new Promise(resolve => {
const fields = {};
const busboy = new Busboy({
// uses request headers to extract the form boundary value
headers: event.headers,
});
// before parsing anything, we need to set up some handlers.
// whenever busboy comes across a file ...
const f = [];
busboy.on("file", (fieldname, filestream, filename, transferEncoding, mimeType) => {
// ... we take a look at the file's data ...
filestream.on("data", data => {
fields[fieldname] = {
filename,
type: mimeType,
content: data,
transferEncoding,
};
});
});
// whenever busboy comes across a normal field ...
busboy.on("field", (fieldName, value) => {
// ... we write its value into `fields`.
fields[fieldName] = value;
});
// once busboy is finished, we resolve the promise with the resulted fields.
busboy.on("finish", () => {
resolve(fields);
});
// now that all handlers are set up, we can finally start processing our request!
busboy.write(event.body);
});
}
/** ***************************************************************************
* Serverless function
**************************************************************************** */
exports.handler = async function(event, context) {
// parse the incoming multipart/form-data data into fields object
const fields = await parseMultipartForm(event);
// create new formdata object to be send to Lever
const form = new FormData();
for (const [key, value] of Object.entries(fields)) {
if (key === "resume") {
// append "resume" with the file buffer and add the file name
form.append("resume", value.content, { filename: value.filename });
} else {
form.append(key, value);
}
}
};
Any guidance you might have would be greatly appreciated.

How to return blob item from localForage in service worker?

in my service worker i store mp4 video in indexedDB with localforage library in a blob data. It's work ! but i don't know how can i return this blob data.
This is my fetchHandler code :
const fetchHandler = async (event) => {
const getResponse = async () => {
const request = event.request;
if( request.destination === 'video' ){
// Get from indexedDB
const value = await localforage.getItem('video');
// How return the video from indexedDB cache ?
if( value ) return value; // not working
// Add in indexedDB
var networkResponse = await fetch(event.request);
localforage.setItem('video', networkResponse.blob() ).then(function (value) {
// Do other things once the value has been saved.
console.log(value);
}).catch(function(err) {
// This code runs if there were any errors
console.log(err);
});
}else{
const openedCache = await caches.open(SW_CACHE_NAME);
const cacheResponse = await openedCache.match(request);
if (cacheResponse) return cacheResponse;
var networkResponse = await fetch(event.request);
const cachePutResponse = await openedCache.put(request, networkResponse.clone());
if (cachePutResponse) return cachePutResponse;
}
return networkResponse;
};
event.respondWith(getResponse());
};
thanks for your help
You need to pass a valid Response object to event.respondWith(). That entails a response body (which is what you get back from localforeage.getItem()), but also some response headers.
You can use the Response constructor to create that, and return it from your getResponse() function.
The code could look something like:
const value = await localforage.getItem('video');
if (value) {
// See https://fetch.spec.whatwg.org/#bodyinit for what's accepted
// as a BodyInit.
return new Response(value, {
headers: {
// Replace this with the actual MIME type for the video.
'content-type': 'video/mp4',
// Include any other headers here if desired.
}
});
}

Question reg expo FileSystem.readAsStringAsync

I'm pretty new to react native and need some help reg. the possiblity to read an image from a file (like an image). I'm using the expo filesystem library with the following code:
const uploadImages = (file) => {
let data = null;
try {
data = await FileSystem.readAsStringAsync(file);
console.log(data)
} catch (err) {
console.log(err)
}
The issue I have is that I get: 'await' is only allowed within async functions
How can I call this function to wait until the data is loaded into the data variable ?
FileSystem.readAsStringAsync(...) returns Promise.
You can use Promise api like .then() and .catch():
const uploadImages = (file) => {
FileSystem.readAsStringAsync(file)
.then(data => {
// Do something with your data in this block
console.log(data);
})
.catch(err => {
console.log(err.message)
})
}

Microsoft Cognitive API keeps telling me : "message": "The input data is not a valid image or password protected."

I have he base64 string of an image and I'm trying to convert it into an 'application/octet-stream' because that's what the api requires. I think I've done that by creating a blob as you can see from my function. When I make the api call I keep getting the message in the title. Anyone know what's wrong?
I think it might be that my blob is not an octet-stream but I've tried both sending the normal base64 string and the blob. Please help, really desperate here
const blobPdfFromBase64String = base64String => {
const byteArray = base64.toByteArray(base64String);
return new Blob([byteArray], { type: 'application/octet-stream' });
};
let img = route.params.image;
const sendImage = async() => {
let url = `${config.ENDPOINT}vision/v3.0/read/analyze`;
let headers = new Headers();
let blob = blobPdfFromBase64String(img.base64);
headers.append('Content-Type', 'application/octet-stream');
headers.append('Ocp-Apim-Subscription-Key', config.KEY);
try {
let response = await fetch(url, { method:'POST', headers, body:blob});
let json = await response.json();
console.log(json)
return json;
} catch (error) {
console.log(`Error in sendImage, ${error}`);
}
}