Can I use the File System Access API (https://web.dev/file-system-access/) to create something like a file explorer within a website (react).
I plan to make a simple online file explorer that lets you browse open a folder and then lets you browse through the folder, play videos and MP3s.
(I know this wasn't possible a few years ago, because it was impossible for js to access anything in the local storage, I just wanted to know if anything have changed or not. If File System Access API is not the way to go, can you suggest some better way to read bulk local files from a folder.)
This is possible with the File System Access API today:
const dirHandle = await window.showDirectoryPicker();
for await (const entry of dirHandle.values()) {
console.log(entry.kind, entry.name);
}
You can explore the folder structure by going deeper if entry.kind is a directory.
For future reference, I'm posting my work; https://github.com/akshayknz/filesystem-access-api/blob/main/file.html (A html page which displays all images from picked folder.)
Note:The API only work in secure contexts (i.e. it works in https:// and file:///)
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
or
const dirHandle = await window.showDirectoryPicker();
const fileHandle = await dirHandle.getFileHandle(entry.name, {});
const file = await fileHandle.getFile();
Related
so I am trying to build a website that allows users to download files that are located in the server computer when the users access the website and click a download button.
I wish to use as few libraries as possible due to some real world limitations. Ideally no Express or Ajax. And I think it should be fully possible with just vanilla node.js
From my search on the internet it seems most of the code is of this form:
const fs = require('fs');
const https = require('https');
// URL of the image
const url = 'GFG.jpeg';
https.get(url,(res) => {
// Image will be stored at this path
const path = `${__dirname}/files/img.jpeg`;
const filePath = fs.createWriteStream(path);
res.pipe(filePath);
filePath.on('finish',() => {
filePath.close();
console.log('Download Completed');
})
})
However, the code doesn't seem to be doing what I want.
First, it requires an url, so it is more about directing a resource online to another location. Whereas I want to actually serve a locally stored file on the server to users when they access the website.
Second, it appears to be downloading to the server computer. But what I want is to let users download to their own client devices. Basically the normal download function you would encounter when you want to download something on the Internet and you see your browser's "Download" section having some new entries.
How can I achieve what I want?
I'm a total noob at this, so it would be great if I can get a skeleton code with some dummy file or pathname.
Appreciate any guidance. Thanks!
You are missing an http.server. http.get just does a web request and as you said you don't want to do that.
Here is some example code creating a server and serving a single file without using express:
const fs = require('fs');
const path = require('path');
const http = require('http');
http.createServer(function(request, response) {
var filePath = path.join(__dirname, '/files/img.jpeg');
response.writeHead(200);
var readStream = fs.createReadStream(filePath);
readStream.pipe(response);
}).listen(2000);
I believe it would not be possible due to security reason as stated in many other articles on StackOverflow. However, when I use the Diagram app at https://app.diagrams.net/ I realized they could ask me to save a file, and somehow keep that file reference and whenever I click Save on the app, my local file on hard drive changes (no new download).
I know it's only possible to upload/download a file and believe you cannot edit it (using Blob with FileReader etc). How do they achieve that? The app is open source but unfortunately plowing through the source code of their File Handler I still cannot find out what API they are using. I don't remember installing any plugin or app in my browser.
I also notice there is this permission in my browser so I guess it's some standard API, but even using that as keyword, all leads back to StackOverflow articles saying it's not possible.
Is it a new API I am not aware of? What am I looking for?
You can use localStorage to achieve this without needing any other permission from the user.
localStorage.setItem("data", JSON.stringify(data));
If your data is just JSON then this would work, however if you have custom data types, you can take a look here.
Edit:
Since you wanted to save the file directly to the device and edit it, you can take a look at File System Access API. This article here explains it.
You can load the file first by using,
let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});
Once you have the file handle you should be able to write to the file without requesting to download a new file everytime there is a change.
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}
The codes are from the article I have linked above and the article explains everything much clearly. It's worth reading.
Say I have a website hosted via Bluehost or the like, at example.com. If I have a file stored at example.com/a.txt, how can I go about reading from this file? And, if I want to write a new string to this file, is it possible to do so, or is it impossible with JavaScript in the web?
you could make a simple api using express and use file-system or fs
with that package you can do that with a single line after doing const fs = require("fs"); :
const constant = fs.readFileSync("path"); //read the file
fs.writeFile("path", "something to write", () => {
//a callback func
});```
In short no. But you have workarounds:
You can open some folder for the public view:
static files - read only access (styles and javascript)
media files - read only access (pictures and other media)
some manually created url - to edit/create the file in the media folder
I have an application on React that shows some information based on a json stored in my Server. So when the user opens my website it gets the JSON and renders it. I want to implement a new function that enables the user also to download a PDF (related to that specific JSON). And my idea is when the JSON is available on my server I generate the PDF (completely server side) and store it. When someone goes on the front and pushes the button to Download the PDF, it goes on my storage and downloads the PDF. If I can generate the pdf based on React Components it would be much easier (because they are already implemented on the React Application).
I am newbie to node but little experienced with React and don't know if it is possible to solve the problem like this but basically my idea was providing React a JSON, then it will generate the MainComponent based on it, then I get the html of this Component and finally generate the PDF to store on the server. On pseudo code:
const fs = require('fs');
let required_data = JSON.parse(fs.readFileSync('myJson.json'));
html = renderToStaticMarkup(<MainComponent initialJson={required_data})
And then with this html I create the pdf with some library like html-pdf, jspdf etc.. and save it to the server. Is it possible somehow to use this approach to solve my problem?
I could solve my problem using Puppeteers headless Chrome.
First I generated the html of my application
html = ReactDOMServer.renderToStaticMarkup(<MainComponent initialJson={required_data} />)
then I opened Puppeteers' Chrome, used the html on page, and printed it to PDF. I got really satisfatory results:
const browser = await Puppeteer.launch(....)
let page = await browser.newPage()
await page.setContent(html)
let pdf = await page.pdf(...); ///This is the PDF File
await browser.close();
I'm trying to dynamically get the images from the NOAA / National Weather Service here
https://radar.weather.gov/ridge/RadarImg/N0R/MTX
using JavaScript and it's proving to be tricky. Even though the names of the image files are standard/predictable, part of the naming convention includes the time at which the image was captured, and those times vary, so it makes more sense to loop through the directory instead of just making a lot of guesses. I know that scanning directories is generally not allowed because of the obvious security issues, so I tried opening it in an iframe, but there is no "index.html" file per se--all the html appears to be automatically generated by the browser, so there is no DOM to work with.
So has anyone dealt with something like this before? I'm stumped.
The server at that URL actually responds with the HTML you see in your browser.
Here is an example to parse the images from this directory in node.js:
const DOM = require('dom-parser')
const axios = require('axios')
axios.get('https://radar.weather.gov/ridge/RadarImg/N0R/MTX/').then((res) => {
const dom = new DOM().parseFromString(res.data)
const imageUrls = dom.getElementsByTagName('a')
.map(link => link.getAttribute('href'))
.filter(url => url && url.match('gif$'))
console.log(imageUrls)
})