How to add files using JSZip from remote URL in ReactJS? - reactjs

I'm using the map function to loop files inside a folder of my zip files but the folder is always empty. The fetching of the main file is working though.
Here is my code:
getZip = async () => {
const zip = new JSZip();
const url = await svc.getMainFileURL(); // will return a downloadable url from s3
let response = await fetch(mcsURL); // will fetch the data from s3 blob
let data = await response.blob(); // and convert it into blob
zip.file(`MainFile.xlsx`, data); // add into the zip file
const otherFiles = zip.folder("files"); // create another folder inside the zip file
// Loop files from source data then insert it in the folder
const list = sourceData.map(async (item,index) => {
const fileUrl = await svc.getOtherFileUrl();
const response = await fetch(fileUrl);
const data = await response.blob();
console.log(data);
otherFiles.file(`${index}.xlsx`, data);
})
zip.generateAsync({type:"blob"})
.then(function(content) {
FileSaver.saveAs(content, `Zip File Name`);
});
}
The logging of data returns fine but when I download the zip file it has only the data of the main file with folder files. Here's a screenshot:
There may be a problem with me using async/await but I can't figure it out. Can anyone help me? Thanks in advance.

Nevermind, I already solved it using Promise.all(). The zip.generateAsync function returns the zip file even if the promises from the map function are not resolved. That's why the folder is always empty. Here is my altered code:
getZip = async () => {
const zip = new JSZip();
const url = await svc.getMainFileURL(); // will return a downloadable url from s3
let response = await fetch(mcsURL); // will fetch the data from s3 blob
let data = await response.blob(); // and convert it into blob
zip.file(`MainFile.xlsx`, data); // add into the zip file
const otherFiles = zip.folder("files"); // create another folder inside the zip file
// Loop files from source data then insert it in the folder
const list = sourceData.map(async (item,index) => {
const fileUrl = await svc.getOtherFileUrl();
const response = await fetch(fileUrl);
const data = await response.blob();
console.log(data);
otherFiles.file(`${index}.xlsx`, data);
return data;
})
// If all prmises are fullfilled it will call the zip
// function and download it using the FileSaver library
Promise.all(list).then(function() {
zip.generateAsync({type:"blob"})
.then(function(content) {
FileSaver.saveAs(content, `Zip File Name`);
});
});
}

Related

React FileReader readAsDataURL not working: URL can't be decoded in flask backend as format == None

I'm working on a basic React web app where user can upload images, and images are send to the flask backend to be processed. I'm using FileReader class to convert the uploaded images through into URLs, and then send them to the backend, where I need to decode the URLs then converted it into an np.array for the processing.
The issue is, when I try to decode the image with image_data = base64.b64decode(image_url) and get the image with Image.open(io.BytesIO(image_data)), somehow it won't recognize the url as an image? Basically I got this error:
raise UnidentifiedImageError(
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x2e8950b30>
I checked the image format with image_format = imghdr.what(io.BytesIO(image_data)), and the image_format equals to None. Do I need to specify the format when encoding the image?
Here's my code:
in React App():
handleImageUploadSelect = (event) => {
let imageURLs = [];
const files = event.target.files;
for ( let i = 0; i < files.length; i++ ) {
// load file object
const file = files[i]
// file reader
const reader = new FileReader();
reader.onload = (event) => {
const dataURL = event.target.result;
// add dataURL to the state variable
imageURLs[i] = dataURL;
}
reader.readAsDataURL(file);
}
this.state.uploadImageURLs = imageURLs;
}
handleImageUpload = event => {
event.preventDefault();
// send uploadImageURLs back to flask server
const data = { images: this.state.uploadImageURLs };
console.log(data)
fetch('http://127.0.0.1:5000/add_images', {
method:'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
},
})
.then((response) => response.json())
.then((data) => {
// response data
console.log(data)
})
.catch((error) => {
console.error(error);
});
}
And in flask server file:
#main.route('/add_images', methods=['POST'])
#cross_origin()
def add_images():
data = request.get_json()
for imageURL in data['images']:
image_data = base64.b64decode(imageURL)
image = Image.open(io.BytesIO(image_data))
image_array = np.array(image)
# processing ...
return jsonify({"condition": "image received"})
Please Help! Thanks!

Pass Files to Node Server

Im having this function in my react app, what is does is sending a file to the server and the server save it to the declared dir.
const handleUploadfile = (event) => {
event.preventDefault();
const data = new FormData();
data.append('file',file );
fetch("http://localhost:4000/upload", {
method: 'POST',
body: data
}).then((response) => console.log(response))
}
heres the code in the node server handling the request above
app.post("/upload", (req, res) => {
const newpath = "./files/";
const file = req.files.file;
const filename = file.name;
file.mv(`${newpath}${filename}`, (err) => {
if (err) {
res.status(500).send({ message: "File upload failed", code: 200 });
}
res.status(200).send({ message: "File Uploaded", code: 200 });
});
});
The upload is working well, but what i want to know is, am i able to include some data like a string directory for each uploaded file something like that.
BTW im using express-uploadfile middleware so i can access the files.
If you want to upload another filed in your request you simply need to call append on your FormData object.
const data = new FormData();
data.append('file',file );
data.append('string','some string');
Then read it on the server
const string = req.body.string;

Convert blob url to file or Base64 to upload to cloudinary

I have converted the file to blob url by creating a canvas,
Now I want to convert blob url to either file type or base64 type to upload to cloudinary.
But it seems very challenging to me, as none of them are working.
The below code is to convert the images to the blob url, acutally I am square cropping them
CanvasUtils.js
export async function getCroppedImg(
imageSrc,
pixelCrop,
...
) {
...
return new Promise((resolve) => {
canvas.toBlob((file) => {
resolve(URL.createObjectURL(file));
}, "image/png");
});
My try's:
Converting blob url to blob oject and then to file format
for (let i = 0; i < imageUrls.length; i++) {
console.log("This is from within the loop: imageURL", imageUrls[i]);
let blob = new Blob([imageUrls[i]], { type: "image/jpg" });
console.log("Blob is ", blob);
var myFile = blobToFile(blob, "myimage.jpg");
// uploading code goes here [find the code below]
}
Converting blob url to blob oject and then to base64
let reader = new FileReader();
reader.readAsDataURL(blob); // converts the blob to base64 and calls onload
reader.onloadend = async function () {
let myFile = reader.result; // data url
// uploading code goes here [find the code below]
}
The uploading code to save it in cloudinary goes like.
console.log(typeof myFile);
data.append("file", myFile);
data.append("upload_preset", "myPreset");
const res = await fetch(
"https://api.cloudinary.com/v1_1/dpurb6xes/image/upload",
{
method: "Post",
body: data,
}
);
const response = await res.json();
console.log(response.secure_url);
Output for try 1 goes like:
Output for try 2 goes like:
What is the good request then ??
In both the cases you are actually converting the imageUrl into blob.
For some reason it doesn't work.
Instead converting the imageUrl directly to the blob worked for me.
The code goes like:
const getBase64FromUrl = async (url) => {
const data = await fetch(url);
const blob = await data.blob();
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
const base64data = reader.result;
resolve(base64data)
};
});
};
And then use the function like this.
const myImage = await getBase64FromUrl(imageUrls[i]);

Downloading Files from Firebase Storage

I have a function that when clicked downloads a file from firebase storage. I have implemented the function as in the firebase documentation v8. I have also applied the cors policy to allow downloads but the problem is that file is still not being downloaded and I am not getting an error.
Kindly help on this.
Below is my download function.
const handleDownloadFile = async file => {
try {
const url = file.downloadURL;
console.log(file);
const xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = event => {
const blob = xhr.response;
};
xhr.open('GET', url);
xhr.send();
} catch (error) {
console.log(error.message);
}
};
The function accepts the details of the file. Below is a sample object that
{
name: 'Ndov network LOGO - 400.png',
downloadURL: 'https://firebasestorage.googleapis.com/v0/b/tkiā€¦=media&token=2680cc-4043-4676-992a-7e64fe8342f2',
uuid: '1b1c0a4b-80a5-42d4-a698-719a26e3f281'
}
kindly help me understand why I am not getting any errors and the still download, not working.
Easiest way to download file on url that comes from API is to
window.open(url,'_blank');
or you can use some library for downloading files in blob format like
https://www.npmjs.com/package/file-saver
This will open a window and ask the user where they want to save the file locally.
import { getStorage, ref, uploadBytes, getBlob } from 'firebase/storage'
export const downloadFile = (refToFile) => {
const storage = getStorage()
const fileRef = ref(storage, refToFile)
const blob = await getBlob(fileRef)
const blobUrl = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = blobUrl
link.download = 'myfilename.pdf'
link.click()
}

File Upload and download JavaScript

EDIT
Hope someone can clarify this issue I am having:
I want to store files in the backend inBinary format, and after get them and convert them into the original state of the file, I believe there is something wrong with my code, I am using HTML upload
this is how I send the binary data to backend:
const handleSubmit = async file => {
let formData = new FormData()
formData.append('file', file)
try {
const res = await postInvoice(uuid, formData)
console.log(res)
setLoadingInvoice(false)
setState({
fileList: [],
attachments: [],
filesConverted: [],
})
}
}
**edit with the api call, only missing hte url part which is in a different file**
export const postInvoice = async (id, data) => {
return await request
.post(BRattachments().post(id))
.send(data)
.set(getHeaders())
}
this is how I try to download te bianrry data:
const handleDownload = async value => {
try {
const res = await getInvoice(value.id)//api call
const file = new Blob([response], {
type: res.type,
})
saveAs(file, value.id + '.' + res.extension)//using save as to save import saveAs from 'file-saver'
}
}
**edited,this is the API CALL,I have them groued in a different file**
export const getInvoice = async ref => {
return await request
.get(BRattachments().getAll(ref))
.send()
.set(getHeaders())
.responseType('blob')
}
the problem is that every time I try to download any saved file, it gives me a problem, with XLS I only see null in the file, with PNG it says file not PNG, etc.
Hope someone can clarify how can I download binary file and convert it in a downloadable file.
thanks

Resources