React-Flask download excel file with button click - reactjs

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

Related

Firebase Storage not displaying image properly (shows a small box)

EDIT: I've updated the CORS config but its still showing the same error.
I have a Tinymce RTE on my page, and when u drop an image into the editor, I have some functions that upload it to firebase storage, then swaps out the src of the text editor with the url fetched from firebase. It works kinda ok, but its being displayed as a broken link image icon.
When I check the link, its because originally it downloads the image when the link is clicked. I added a metadata property when it uploads it, but now its just showing a tiny box.
Here is the code where the image dropped into the editor is uploaded into firebase storage
const imagesUploadHandler = async (blobInfo, success, failure) => {
try {
const file = blobInfo.blob();
const storageRef = ref(storage, file.name);
const metadata = {
contentType: 'image/jpeg',
};
await uploadBytes(storageRef, file, metadata);
const url = await getDownloadURL(storageRef);
console.log(url);
return url;
} catch (error) {
// Call the failure callback with the error message
console.log(error.message);
}
};
Originally, i didnt include the contentType metadata, and it was just uploading as application/octet-stream, which i assume is why it prompts you to save the image.
Image link: https://firebasestorage.googleapis.com/v0/b/cloudnoise-news.appspot.com/o/ref.jpg?alt=media&token=1edc90e7-1668-4a06-92a3-965ce275798b
Currently its displaying this
Somethings i checked through
firebase storage rules is in test mode, so should be able to read and write by anyone.
i tried sticking in different MIME types but it either shows the tiny box, or it shows "undefined"
the files upload successfully and the "swap" in Tinymce editor is also all good.
Any idea why this is happening?
you need to set the metadata tag
const metadata = {
contentType: file.type,
};
This should ensure that the correct content type is set when the image is uploaded to Firebase Storage.
If this does not resolve the issue, you may need to check that the URL returned from getDownloadURL is valid and points to the correct image. You can try opening the URL in a new browser tab to verify that the image is accessible.
I fixed it by adding a blob, I created a blob object with the file data, then i just made it upload the blob object instead of the single file.
const imagesUploadHandler = async (blobInfo, success, failure) => {
try {
const file = blobInfo.blob();
const storageRef = ref(storage, file.name);
const metadata = {
contentType: file.type,
};
// Create a new Blob object with the file data
const blob2 = await new Blob([file], { type: file.type });
// Upload the Blob to Firebase Storage
await uploadBytes(storageRef, blob2, metadata);
const url = await getDownloadURL(storageRef);
console.log(url);
return url;
} catch (error) {
// Call the failure callback with the error message;;
console.log(error.message)
}
};

Uploading file on Hapi.js server

I'm trying to upload file on a hapi server, and my goal would be to upload a zip file and unzip it on the server, but I currently have problems withs the upload part for a single file...
my frontend is made with react and I'm selecting a file with a <input>
my route is made like this
method: 'POST',
path: '/upload',
config: {
payload: {
maxBytes: 209715200,
output: 'stream',
parse: true
},
handler: handlers.uploadFile,
description: 'upload file'
}
});
I used a stream type output, but I can't figure out what is the type to used depending on the situation between stream, data, or file.
Here my handler uploadfile() is this one :
handler.uploadFile = async (req, h) => {
var doc = req.payload
return true;
}
But I can't get any informations on my file like doc.name or doc._hapi.name so I don't really know how to use the data here.
If someone know a site where all of this is explain, or could help me on that that would help a lot !
Thanks !
Ok so I just figure out what the problem was.
I needed to pass my data as a formData from my react component like that
var formData = new FormData();
formData.append("file", data)
if anyone have the same problem, that is a solution I suppose

Download large files using React and AspnetCore to open browser save (headers)

I'm struggling with the problem of downloading large files using a web API in asp net core and frontend in React.
When the file starts downloading it doesn't show the dialog browser (Save As File Dialog) until it downloads the file in memory and next gives the possibility to save it.
When the file is bigger, like 200MB, the user can't choose where to save the file before start downloading it and see the download progress in the browser tab.
This is to use with react frontend and web API in aspnet core.
After reading for some hours I couldn't find the solution.
I can't use a link to download the file because I need to authenticate with a token.
Maybe I am missing any configuration or setup in my backend/frontend?
Any suggestions or advice will be very appreciated.
The method of my web api:
[HttpGet("{fileName}")]
[Authorize]
public IActionResult GetFile(string fileName)
{
Stream stream = _fileManager.GetFileContent(fileName);
// Response...
ContentDisposition cd = new ContentDisposition("attachment")
{
FileName = fileName,
// DispositionType = "attachment; filename=" + fileName + ";",
Inline = false // false = prompt the user for downloading; true = browser to try to show the file inline
};
Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());
return File(stream, MediaTypeNames.Application.Zip);
}
The frontend using axios to get it.
async function Download() {
var authToken = await authService.Token();
console.log("calling request", process.env.REACT_APP_API_URL + "files/GetFile/iPro.zip");
if (authToken) {
BioAxios.get("/files/GetFile/file.zip", {
responseType: "blob",
headers: {
Authorization: "Bearer ".concat(authToken.access_token),
"Content-Type": "application/zip"
}
}).then(response => {
// Log somewhat to show that the browser actually exposes the custom HTTP header
console.log("Full Response", response);
// Let the user save the file.
FileSaver.saveAs(response.data, "file.zip");
});
}
}

Where is the Ionic/Cordova dataDirectory folder?

I'm building an Ionic app using the Ionic Native File plugin. I need the app to be able to read a file that I've saved in the app itself, but I don't understand where I need to store the file. The official Cordova documentation says something about a certain cordova.file.dataDirectory, whereas the Ionic documentation uses this example:
import { File } from '#ionic-native/file';
constructor(private file: File) { }
...
this.file.checkDir(this.file.dataDirectory, 'mydir').then( //stuff).catch( //stuff);
I don't understand where I need to put my file so that the app can read them.
Do not use file:///android_asset/
You can store the file in file.dataDirectory
Storing the file
I am using http to download a zip. I then unzip and delete the zipped file afterwards.
const down = this.http.downloadFile(uri, {}, {}, path + 'data.zip')
.then(data => {
console.log(data.status);
console.log("DOWNLOAD SUCCESS");
this.desc = "Extracting";
this.loading = 100;
this.downloading = false;
this.zip.unzip(path + 'data.zip', path, (this.UnzipProgress))
.then((result) => {
if(result === 0) this.file.removeFile(path,'data.zip');
if(result === -1) console.log('UNZIP FAILED');
});
})
.catch(error => {
console.log("ERROR::");
console.log(error.status);
console.log(error.error); // error message as string
console.log(error.headers);
});
Retrieving the file
The only thing that worked for me was convertFileSrc()
let win: any = window;
let safeURL = win.Ionic.WebView.convertFileSrc(this.file.dataDirectory+'data/yourFile.png');
Hope this helps

React-native-android - How to save an image to the Android file system and view in the phone's 'Gallery'

Is it possible to save an image to the android's local file system so it can be viewed from the phone's 'Gallery' and in a folder??
I found this react-native-fs library but after studying the documentation and working through an example I am still unsure if it is possible.
Thanks
For anyone having the same problem, here is the solution.
Solution
I am using the File System API from the react-native-fetch-blob library. This is because I tought it was way better documented and easier to understand than the 'react-native-fs' library.
I request an image from the server, receive a base64 and I then save it to the Pictures directory in the android fs.
I save the image like this:
var RNFetchBlob = require('react-native-fetch-blob').default;
const PictureDir = RNFetchBlob.fs.dirs.PictureDir;
getImageAttachment: function(uri_attachment, filename_attachment, mimetype_attachment) {
return new Promise((RESOLVE, REJECT) => {
// Fetch attachment
RNFetchBlob.fetch('GET', config.apiRoot+'/app/'+uri_attachment)
.then((response) => {
let base64Str = response.data;
let imageLocation = PictureDir+'/'+filename_attachment;
//Save image
fs.writeFile(imageLocation, base64Str, 'base64');
console.log("FILE CREATED!!")
RNFetchBlob.fs.scanFile([ { path : imageLocation, mime : mimetype_attachment } ])
.then(() => {
console.log("scan file success")
})
.catch((err) => {
console.log("scan file error")
})
}).catch((error) => {
// error handling
console.log("Error:", error)
});
},
The following code that is in the above method refreshes the Gallery otherwise the images would not display untill the phone is turned off and back on again.
RNFetchBlob.fs.scanFile([ { path : imageLocation, mime : mimetype_attachment } ])
.then(() => {
console.log("scan file success")
})
.catch((err) => {
console.log("scan file error")
})
Enjoy!
You can absolutely do this with react-native-fs. There's a PicturesDirectoryPath constant which isn't mentioned in the README for the project; if you save a file into there it should appear in the Gallery app. If you want it to appear in your own album, just make a new directory in that folder and save the file into there, eg
const myAlbumPath = RNFS.PicturesDirectoryPath + '/My Album'
RNFS.mkdir(myAlbumPath)
.then(/* write/copy/download your image file into myAlbumPath here */)
I don't have full example code anymore sorry, because I ended storing images in my app's private cache directory instead. Hope this helps anyway!

Resources