I am trying to create a simple folder uploader (client side). The minimum required functionality is to be able to select a folder/file(s) and show on the browser the information of all files. I have used a simple input element:
const ReadFolder = () => {
const onFileChange = (event: React.ChangeEvent<HTMLInputElement>) => console.log(event.target.files);
return (
<input
type='file'
directory
webkitdirectory
multiple
onChange={onFileChange}
/>
);
}
The onFileChange function just shows the info of received file list.
It works fine for small folders, but when I try to upload a git repository from my computer (which has a large nested folder hierarchy), the browser window becomes unresponsive for around 2 minutes before the onChange event is reported. Is there a way I can avoid this unresponsiveness? Can I push this processing to background (or to a web worker)?
This processing may not even be done by the browser's process, but rather by the OS directly, which is building a list of metadata for all the files in the directory and its sub-directories. That is a lot of I/O.
You are not the first one to report such an issue with some configurations (OS or file system, it's still unclear to me) having trouble to generate files' metadata when being asked by the browser through the <input type="file">.
So moving whatever to a Worker would most probably not help at all. My educated guess would be that your HDD is the bottleneck, not the CPU.
What you can try in supporting browsers, is to request a handle over the directory rather than requesting all the files in a single call.
The new File System API has a showDirectoryPicker method which would allow you to gain access to the directory, and to read only the files you need, and if you need them all, to do this in a streaming manner, allowing your page to render part of what has already been parsed while it is being parsed.
You can see a live demo here, which will currently only work in Chrome.
Note that directories gotten from a drag&drop event should not be read entirely either, and that you should also be able to navigate them by batches, with better browser support, so if you can, try to make your UI force your users to use this method instead.
Related
I have a C++ app that uses WebView2 as UI component. Native-side code and web-side code communicate via a host object. That works great, but:
I want to let the user (for example) drag and drop files to a drop box on the UI, hand the path names over to the client C++ app, which should read and process the files. Butfor this I would need the full path names (on the host).
I have currently no example for the other way round, but I could imagine to hand a path name to JavaScript which should the read and process this file.
I couldn't find any documentation neither on WebView2, nor in the File Aystem Access API on the Browser side (Java Script).
I know that there are security issues for real web apps, but - hey - this is a native component anyway!
So here is my code in JavaScript:
butOpenFile.addEventListener('click', async () => {
// Destructure the one-element array.
[fileHandle] = await window.showOpenFilePicker();
// Do something with the file handle.
});
How can I use *fileHandle *to retrieve the full path of the selected file, that the hostObject can use to open and process the file? (Note: fileHandle.name only has the name.ext-part of the path)
I'm working with an extremely old database system containing people and associated PDFs. I can access most data over a webbrowser, however PDFs cannot be requested via web-api - I do however have the liberty of loading any javascript library, and use chrome webdev console.
I want to get a proof of principle working, where I can load a person's PDFs. But I'm not quite sure what the best approach is.
Idea to upload a file to the website's local storage in my browser (since it's viewed several times). However I seem to be lacking a good library to save/load files from the cache directory. This library wasn't updated since 2016 and Filesaver.js doens't seem to be keen on loading the files after saving. Using a fully-fledged database implementation seems overkill (most files will be <= 5-10MB)
Loading a file from local storage (even if dir is added to workspace in chrome) seems completely impossible, that would've been an alternative
adding the local file path to a <a href=""> element did not work in chrome
Is there a feasible approach to manage/associate PDF files on my local drive with the website I'm working with (and have full client-side control, i.e. can load any library)?
Note: Access is restricted, no chrome addons can be used and chrome cannot be started using custom flags
I don't exactly know what you are asking for, but this code will get all the pdfs in a selected directory and display them and also makes a list of all the file objects. This will only work in a "secure context" and on chrome
(it also wont run in a sandbox like a stackoverflow code snippet)
js
let files = [];
async function r() {
for await (const [_, h] of (await window.showDirectoryPicker()).entries()) files.push(await h.getFile());
files = files.filter(f => f.type === "application/pdf");
for (const f of files) {
let e = document.createElement("embed");
e.src = URL.createObjectURL(f), e.type = f.type;
document.body.appendChild(e);
}
}
html
<button onclick="r()">read PDFs</button>
also you can probably use this if you need to send the local PDF somewhere
not sure this answers the question but i hope it helps
Since ActiveX controls are no longer available browsers can display a PDF or a user can download the pdf.
For any more control over that I suspect you could try render the pdf using a JavaScript library like https://mozilla.github.io/pdf.js/
For full control you wont be in a position to control the PDF version, you could alternatively render the PDFs to images on the server and display image versions of the pages.
I’m a bit new to javascriipt/nodejs and its packages. Is it possible to download a file using my local browser or network? Whenever I look up scraping html files or downloading them, it is always done through a separate package and their server doing a request to a given url. How do I make my own computer download a html file as if I did right click save as on a google chrome webpage without running into any server/security issues and errors with javascript?
Fetching a document over HTTP(S) in Node is definitely possible, although not as simple as some other languages. Here's the basic structure:
const https = require(`https`); // use http if it's an http url;
https.get(URLString, res => {
const buffers = [];
res.on(`data`, data => buffers.push(data));
res.on(`end`, ()=>{
const data = Buffer.concat(buffers);
/*
from here you can do what you want with the data. You can write it to a file
with fs, you can console.log it using data.toString(), etc.
*/
});
})
Edit: I think I missed the main question you had, give me a sec to add that.
Edit 2: If you're comfortable with doing the above, the way you access a website the same way as your browser is to open up the developer tools (F12 on Chrome) go to the network tab, find the request that the browser has made, and then using http(s).get(url, options, callback), set the exact same headers in the options that you see in your browser. Most of the time you won't need all of them, all you'll need is the authentication/session cookie.
I'm working on an HTML/javascript app intended to be run locally.
When dealing with img tags, it is possible to set the src attribute to a file name with a relative path and thereby quickly and easily load an image from the app's directory. I would like to use a similar method to retrieve a text file from the app's directory.
I have used TideSDK, but it is less lightweight. And I am aware of HTTP requests, but if I remember correctly only Firefox has taken kindly to my use of this for local file access (although accessing local images with src does not appear to be an issue). I am also aware of the FileReader object; however, my interface requires that I load a file based on the file name and not based on a file-browser selection as with <input type="file">.
Is there some way of accomplishing this type of file access, or am I stuck with the methods mentioned above?
The browser will not permit you to access files like that but you can make javascript files instead of text files like this:
text1.js:
document.write('This is the text I want to show in here.'); //this is the content of the javascript file
Now call it anywhere you like:
<script type="text/javascript" src="text1.js"></script>
There are too many security issues (restrictions) within browsers making many local web-apps impossible to implement so my solution to a similar problem was to move out of browsers and into node-webkit which combines Chromium + Node.js + your scripts, into an executable with full disk I/O.
http://nwjs.io/
[edit] I'm sorry I thought you wanted to do this with TideSDK, I'll let my answer in case you want to give another try to TideSDK [/edit]
I'm not sure if it's what you're looking for but I will try to explain my case.
I've an application which allow the user to save the state of his progress. To do this, I allow him to select a folder, enter a filename and write this file. When the user open the app, he can open the saved file, and get back his progress. So I assume this enhancement is similar of what you are looking for.
In my case, I use the native File Select to allow the user to select a specific save (I'm using CoffeeScript) :
Ti.UI.currentWindow.openFileChooserDialog(_fileSelected, {
title: 'Select a file'
path: Ti.Filesystem.getDocumentsDirectory().nativePath()
multiple: false
})
(related doc http://tidesdk.multipart.net/docs/user-dev/generated/#!/api/Ti.UI.UserWindow-method-openFileChooserDialog)
When this step is done I will open the selected file :
if !filePath?
fileToLoad = Ti.Filesystem.getFile(scope.fileSelected.nativePath())
else
fileToLoad = Ti.Filesystem.getFile(filePath)
data = Ti.JSON.parse(fileToLoad.read())
(related doc http://tidesdk.multipart.net/docs/user-dev/generated/#!/api/Ti.Filesystem)
Please note that those snippets are copy/paste from my project and they will not work without the rest of my code but I think it's enough to illustrate you how I manage to open a file, and read his content.
In this case I'm using Ti.JSON.parse because there is only javascript object in these files but in your case you can just get the content. The openFileChooserDialog isn't mandatory, if you already know the file name, or if you get it from another way you can use Ti.Filesystem in your own way.
I'm a beginner! I need to read data inside txt files in a local folder offline. I know the folder path, but I don't know the name of every single file.
C:\mypath\first.txt
C:\mypath\second.txt
C:\mypath\third.txt
...
To read a sigle file now I use:
$.ajax({url:"C:\mypath\first.txt",
success:function(result){
//...code for storing the data in a variable...
}
});
How can i read multiple file at once without know their name? something like:
$.ajax({url:"C:\mypath\*.txt",
success:function(result){
//...code for storing the data in a variable...
}
});
Thank you for any help!
You can use a file picker control (ie, <input type="file" multiple />) in a supported browser and have the user select the set of files to iterate. User input is the only way to get the list of files - you can't just go mucking about in a user's file system over the internet. All you can learn about the user's system is what the user tells you (eg, through <input type="file" multiple />).
And even then, you won't be able to read the file with a simple Ajax request. Same origin policies apply to local files. It may work if you test it on your own machine, but as soon as it hits the web, it will fail.
The only way to look through a client file system without user interaction is by using a Scripting.FileSystemObject ActiveXControl on windows in a non-internet based HTML Application (.hta file). So, since you don't want to use ActiveXControls, user input is your only option.
Edit: If you are creating a FireFox add-on, you can access the file system. See the documentation at mozilla.org for details.