I'm just trying out the file system API.
As described in http://www.html5rocks.com/en/tutorials/file/filesystem
code:
window.webkitStorageInfo.requestQuota(PERSISTENT, 1024 * 1024, function (grantedBytes) {
window.requestFileSystem(PERSISTENT, grantedBytes, successCallback, errorHandler);
}, function (e) {
console.log('Error', e);
});
function successCallback(fs) {
window.fileSystem = fs;
fs.root.getFile('kiki.txt', {
create: false,
exclusive: true
},
function (fileEntry) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function (e) {
console.log('Write completed.');
};
fileWriter.onerror = function (e) {
console.log('Write failed: ' + e.toString());
};
fileWriter.seek(fileWriter.length);
// Create a new Blob and write it to log.txt.
var blob = new Blob(['Lorem Ipsum'], {
type: 'text/plain'
});
fileWriter.write(blob);
}, errorHandler);
}, errorHandler);
}
(the create: false is because I already created that file before).
Chrome asks permission to use the file system and I grant it.
When I try to read it, I can, it's persistent. But where is it saved?
According to the docs, it is saved in the root folder ("/"), but it is not there (I'm using nginx). I search the entire HD for this file ("kiki.txt") and it is not found.
So where is it saved?
You are using the HTML5 file system APIs but trying to find data files on the server.
Client browsers will save the data most probably on the client's file system. Quote from the link you provided: http://www.html5rocks.com/en/tutorials/file/filesystem/
With the FileSystem API, a web app can create, read, navigate, and write to a sandboxed section of the user's local file system.
As for your question - each browser will have their own implementation of the HTML5 file system APIs and the data might be saved anywhere using custom format.
As a key value pair in a database stored in the user profile which may be different for each person based on operating system, browser, and configuration.
But here is one example, copied from:Where is the html5 local database located on a client machine?
C:\Users\<user>\AppData\Roaming\Mozilla\Firefox\Profiles\<profile-name>\webappsstore.sqlite
Related
I want to create a Chrome extension, that records HTTP requests (to a pre-defined host) and persists them as a list in local storage so when I call a particular website again the list will be extended.
I want to go with Manifest v3 to make the extension "ready for the future". I created a background script to trigger the request that currently puts all the details into local storage like that (currently this is redundant for demonstration purposes, I also tried it seperated):
chrome.webRequest.onBeforeRequest.addListener(details => {
var urls = [];
chrome.storage.local.get(['data'], function(data){
urls = data.urls;
});
chrome.scripting.executeScript(
{
target: {tabId: details.tabId},
func: recordClick,
args: [details, urls]
},
() => {
urls.push(details);
console.log(urls.length);
chrome.storage.local.set({urls: urls});
});
}, {
urls: ['<all_urls>']
});
There's another function called recordClick() that does the same as in the callback:
function recordClick(details, urls) {
urls.push(details.url);
chrome.storage.local.set({urls: urls});
}
I tried several ways on where to load and save the result but none of them work. When I load the previous urls within the onBeforeRequest trigger, urls is not global and not known within the callback. When I put it outside the trigger definition, it's not reading the storage in realtime. I also tried to load the urls in a content script, loaded at "Document start". I tried to load the urls in the backend script at the top, and so on.
Seems like I have a timing problem: The trigger always loads an empty list or the variable is not global. I'm not able to extend the list. No matter where I put the storage functions.
Is my plan feasable at all? What am I'm doing wrong?
thanks!
Since chrome.storage.local.get is asynchronous, you should move chrome.scripting.executeScript into the callback of it.
onComplete may be suitable for your purpose, instead of onBeforeRequest.
chrome.webRequest.onBeforeRequest.addListener(details => {
chrome.storage.local.get('urls', function(data){
let urls = [];
if( data.urls ) {
urls = data.urls;
}
urls.push(details);
chrome.storage.local.set({urls: urls}, function() {
console.log('Value is set to ');
console.log(urls);
});
chrome.scripting.executeScript( {
target: {tabId: details.tabId},
func: function(details, urls){ console.log("executed script") },
args: [details, urls]
},
() => {
console.log("injected")
});
});
},
{ urls: ['<all_urls>'] }
);
I am following a tutorial to resize images via Cloud Functions on upload and am experiencing two major issues which I can't figure out:
1) If a PNG is uploaded, it generates the correctly sized thumbnails, but the preview of them won't load in Firestorage (Loading spinner shows indefinitely). It only shows the image after I click on "Generate new access token" (none of the generated thumbnails have an access token initially).
2) If a JPEG or any other format is uploaded, the MIME type shows as "application/octet-stream". I'm not sure how to extract the extension correctly to put into the filename of the newly generated thumbnails?
export const generateThumbs = functions.storage
.object()
.onFinalize(async object => {
const bucket = gcs.bucket(object.bucket);
const filePath = object.name;
const fileName = filePath.split('/').pop();
const bucketDir = dirname(filePath);
const workingDir = join(tmpdir(), 'thumbs');
const tmpFilePath = join(workingDir, 'source.png');
if (fileName.includes('thumb#') || !object.contentType.includes('image')) {
console.log('exiting function');
return false;
}
// 1. Ensure thumbnail dir exists
await fs.ensureDir(workingDir);
// 2. Download Source File
await bucket.file(filePath).download({
destination: tmpFilePath
});
// 3. Resize the images and define an array of upload promises
const sizes = [64, 128, 256];
const uploadPromises = sizes.map(async size => {
const thumbName = `thumb#${size}_${fileName}`;
const thumbPath = join(workingDir, thumbName);
// Resize source image
await sharp(tmpFilePath)
.resize(size, size)
.toFile(thumbPath);
// Upload to GCS
return bucket.upload(thumbPath, {
destination: join(bucketDir, thumbName)
});
});
// 4. Run the upload operations
await Promise.all(uploadPromises);
// 5. Cleanup remove the tmp/thumbs from the filesystem
return fs.remove(workingDir);
});
Would greatly appreciate any feedback!
I just had the same problem, for unknown reason Firebase's Resize Images on purposely remove the download token from the resized image
to disable deleting Download Access Tokens
goto https://console.cloud.google.com
select Cloud Functions from the left
select ext-storage-resize-images-generateResizedImage
Click EDIT
from Inline Editor goto file FUNCTIONS/LIB/INDEX.JS
Add // before this line (delete metadata.metadata.firebaseStorageDownloadTokens;)
Comment the same line from this file too FUNCTIONS/SRC/INDEX.TS
Press DEPLOY and wait until it finish
note: both original and resized will have the same Token.
I just started using the extension myself. I noticed that I can't access the image preview from the firebase console until I click on "create access token"
I guess that you have to create this token programatically before the image is available.
I hope it helps
November 2020
In connection to #Somebody answer, I can't seem to find ext-storage-resize-images-generateResizedImage in GCP Cloud Functions
The better way to do it, is to reuse the original file's firebaseStorageDownloadTokens
this is how I did mine
functions
.storage
.object()
.onFinalize((object) => {
// some image optimization code here
// get the original file access token
const downloadtoken = object.metadata?.firebaseStorageDownloadTokens;
return bucket.upload(tempLocalFile, {
destination: file,
metadata: {
metadata: {
optimized: true, // other custom flags
firebaseStorageDownloadTokens: downloadtoken, // access token
}
});
});
I'm using the following when trying to open a local file:
some document
When I click the above in a browser, it opens Finder to the folder. But does not open the file. Should I be doing something else to have the file open in Numbers?
You cannot open local files on the client. This would be a huge security risk.
You can link to files on your server (like you did) or you can ask the client for a file using <input type="file">
You can only open some types of files in browsers, like html css js and mp4, otherwise the browser will want to download it. Also remember that browsers replace spaces with %20. I recommend right clicking the file and opening it with chrome then copy that link and using it.
You can open files that are local as long as it is a file that is on the file that is trying to open another file is local.
Your issue is likely the space in the document name. Try this instead:
some document
The %20 will be read by your browser as a space.
Update
The other answer points out something I missed. The .numbers extension will not be able to be opened directly by your browser. Additionally the other answer describes the security risk this could create.
The File API in HTML 5 now allows you to work with local files directly from JS (after basic user interaction in selecting the file(s), for security).
From the Mozilla File API docs:
"The File interface provides information about files and allows JavaScript in a web page to access their content.
File objects are generally retrieved from a FileList object returned as a result of a user selecting files using the <input> element, from a drag and drop operation's DataTransfer object, or from the mozGetAsFile() API on an HTMLCanvasElement."
For more info and code examples, see the sample demo linked from the same article.
This might not be what you're trying to do, but someone out there may find it helpful:
If you want to share a link (by email for example) to a network file you can do so like this:
file:///Volumes/SomeNetworkFolder/Path/To/file.html
This however also requires that the recipient connects to the network folder in finder --- in menu bar,
Go > Connect to Server
enter server address (e.g. file.yourdomain.com - "SomeNetworkFolder" will be inside this directory) and click Connect. Now the link above should work.
Here is the alternative way to download local file by client side and server side effort:
<a onclick='fileClick(this)' href="file://C:/path/to/file/file.html"/>
js:
function fileClick(a) {
var linkTag = a.href;
var substring = "file:///";
if (linkTag.includes(substring)) {
var url = '/v/downloadLocalfile?path=' +
encodeURIComponent(linkTag);
fileOpen(url);
}
else {
window.open(linkTag, '_blank');
}
}
function fileOpen(url) {
$.ajax({
url: url,
complete: function (jqxhr, txt_status) {
console.log("Complete: [ " + txt_status + " ] " + jqxhr);
if (txt_status == 'success') {
window.open(url, '_self');
}
else {
alert("File not found[404]!");
}
// }
}
});
}
Server side[java]:
#GetMapping("/v/downloadLocalfile")
public void downloadLocalfile(#RequestParam String path, HttpServletResponse
response) throws IOException, JRException {
try {
String nPath = path.replace("file:///", "").trim();
File file = new File(nPath);
String fileName = file.getName();
response.setHeader("Content-Disposition", "attachment;filename=" +
fileName);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
response.setStatus(200);
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int numBytesRead;
while ((numBytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, numBytesRead);
}
// out.flush();
in.close();
out.close();
}
else {
response.setStatus(404);
}
} catch (Exception ex) {
logger.error(ex.getLocalizedMessage());
}
return;
}
You can expose your entire file system in your browser by using an http server.
caddy2 server
caddy file-server --listen :2022 --browse --root /
serves the root file system at http://localhost:2022/
python3 built-in server
python3 -m http.server
serves current dir on http://localhost:8000/
python2 built-in server
python3 -m SimpleHTTPServer
serves current dir on http://localhost:8000/
This s
Good day
I am reading HTML files from an external server via JQuery AJAX call, and storing them on a local IOS 6.0 device with FileWriter. I then read the locally stored files with FileReader and I successfully get the text. What I want to achieve from here, is to take the HTML content from the locally stored file (retrieved via FileReader), and push it into the local Safari Browser on the phone for displaying the HTML page (current target market is iPhone 5). Below is some code. Any ideas how to achieve this? I have tried window.open after installing the InAppBrowser plugin (which I do not really want to use because I want to use Safari) and also returning the text in the onloadend event... document.write is also not ideal as I want to open the file in a new window/tab so that it can be closed to direct the user back to the app when done. I am also not sure if I should read as Binary or Text (assuming TEXT would be the right option because it is not a media file)
Please note that I am new to PhoneGap so my methods used may not reflect Best Practice...
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady () {
var fileName = 'some_file.html';
readerObject.setFileName(fileName);
//Instantiate reader on the file
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
readerObject.gotFS, readerObject.fail);
}
// Create reader
var readerObject = {
// Sets the file name to read from
setFileName : function(fileName) {
readerObject.fileName = fileName;
},
// Gets the file name to read from
getFileName : function() {
return readerObject.fileName;
},
// Capture the file system
gotFS : function(fileSystem) {
fileSystem.root.getFile(readerObject.getFileName(), null,
readerObject.gotFileEntry, readerObject.fail);
},
gotFileEntry : function(fileEntry) {
fileEntry.file(readerObject.readData, readerObject.fail);
},
**readData : function(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
//Return text for streaming into the browser (NOT WORKING)
//return evt.target.result;
//Capture file path
var filePath = file.fullPath+"/"+file.name;
//Open file in new window (NOT WORKING)
//window.open(filePath, '_blank', 'location=yes');
window.open("file:///"+filePath, '_blank', 'location=yes');
};
reader.readAsText(file);
//reader.readAsBinaryString(file);
},**
fail : function(error) {
alert(error.code);
}
}
I am developing a Chrome Extesion for the first time and I am following the only guide that explains something about that: HTML5 ROCKS - FILESYSTEM.
I need to get storage for my extension and I resolved so:
window.webkitStorageInfo.requestQuota(window.PERSISTENT,1024*1024, onInitFs, errorHandler);
Ok, it works.
Now I need to create a xml file into the root, but in "onInitFs" the "fs" var is only a number and "fs.root" can't get it.
function onInitFs(fs){
console.log(fs.root); // -> Undefined
fs.root.getFile('list.xml', {create: true, exclusive: true}, function(fileEntry) {
fileEntry.isFile === true;
fileEntry.name == 'list.xml';
fileEntry.fullPath == '/list.xml';
}, errorHandler);
}
Can anybody explain why it doesn't work and how to resolve this issue?
Using RequestFileSystem within Chrome Extension
In order to use the FileSystem API as a root filesystem for your Chrome extension, you can actually use window.webkitRequestFileSystem instead of requestQuota.
window.webkitRequestFileSystem(window.PERSISTENT, 1024 * 1024, function (filesystem) {
console.log(filesystem);
console.log(filesystem.root);
}, function (e) { console.log("Could not request File System"); });
This does print correctly on Chrome 15,16 and 17 for me:
DOMFileSystem
DirectoryEntry
Using requestQuota for HTML5 apps
Just for reference, this would be the way to actually request the quota (i.e., when not using a Chrome Extension). You have to request the quota (the user sees a little banner at the top of his/her window) first. The RequestFileSystem is called if the user accepts.
window.webkitStorageInfo.requestQuota(PERSISTENT, 1024*1024, function(grantedBytes) {
window.webkitRequestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler);
}, function(e) {
console.log('Error requesting filesystem', e);
});
Eventually it might be necessary to request quota within an extension. Currently this can be circumvented with the unlimitedStorage permission. For the current state of implementation/storage types, see http://code.google.com/chrome/whitepapers/storage.html
Until current stable version 17.x, you cannot use HTML5 FileSystem API in Chrome extension. I have try this, the browser will crash down if I call FileSystem API in background page.
And here is a HTML5 API list what you can use in Chrome extension:
http://code.google.com/chrome/extensions/api_other.html