I'm currently developing my first Chrome app that we'll be used as a Kiosk app later.
I'm trying to read a file at the startup of the app, that file is a config file (.json). It contains values that will be passed inside a URL once the app has launched (ie: www.google.com/key=keyValueInTheJsonFile).
I used https://developer.chrome.com/apps/fileSystem (the method "chooseEntry" especially) to be able to read a file, but in my case I would like to directly specify the path/name of the file and not ask the user to select a file. Like that I can pass the values to the redirected URL at the startup.
Any idea of how I could possibly do that?
Thanks!
If your file is in the package you can read it using simple XHR or Fetch.
You can't use web filesystem since it has different purpose and Chrome filesystem (user's FS) won't work here either since it needs a user interaction.
Use function getURL to get a full URL to the resource and then make XHR call:
var rUrl = chrome.runtime.getURL('file.json');
fetch(rUrl).then((response) => {
return response.json();
})
.then((fileContent) => {
// the content
})
.catch((cause) => console.log(cause));
Related
The Blazor app in Visual Studio uses a Http.GetFromJsonAsync call to get the data for Weather Forecasts from a json file in wwwroot.
When I change the data in the file, I still see the same data in the table?
When I copy the file, and change the code to use the new filename, I get the changed results.
Is there some caching happening with wwwroot files? I've tried hard refresh, that doesn't make a difference, but changing browser does. I know that Blazor caches the framework files...but is this happening to all wwwroot, how do I change this behaviour?
Thanks in advance.
The fetchdata sample page (from new blazorwasm) retrieves data on initialize component:
protected override async Task OnInitializedAsync()
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}
When you go out of this page and come back, initialize is running again and a request is done.
But, because this is a GET request, the browser can deliver answer from cache:
They are some ways to avoid cache on Blazor GET requests, learn about it here: Bypass HTTP browser cache when using HttpClient in Blazor WebAssembly
Also, you can use the simple trick to add a random string to query string:
protected override async Task OnInitializedAsync()
{
var randomid = Guid.NewGuid().ToString();
var url_get = $"sample-data/weather.json?{randomid}";
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>(url_get);
}
In short, it seems to get cached because a get request can be cached by browser and is the browser who retrieve the data.
Over the years on snapchat I have saved lots of photos that I would like to retrieve now, The problem is they do not make it easy to export, but luckily if you go online you can request all the data (thats great)
I can see all my photos download link and using the local HTML file if I click download it starts downloading.
Here's where the tricky part is, I have around 15,000 downloads I need to do and manually clicking each individual one will take ages, I've tried extracting all of the links through the download button and this creates lots of Urls (Great) but the problem is, if you past the url into the browser then ("Error: HTTP method GET is not supported by this URL") appears.
I've tried a multitude of different chrome extensions and none of them show the actually download, just the HTML which is on the left-hand side.
The download button is a clickable link that just starts the download in the tab. It belongs under Href A
I'm trying to figure out what the best way of bulk downloading each of these individual files is.
So, I just watched their code by downloading my own memories. They use a custom JavaScript function to download your data (a POST request with ID's in the body).
You can replicate this request, but you can also just use their method.
Open your console and use downloadMemories(<url>)
Or if you don't have the urls you can retrieve them yourself:
var links = document.getElementsByTagName("table")[0].getElementsByTagName("a");
eval(links[0].href);
UPDATE
I made a script for this:
https://github.com/ToTheMax/Snapchat-All-Memories-Downloader
Using the .json file you can download them one by one with python:
req = requests.post(url, allow_redirects=True)
response = req.text
file = requests.get(response)
Then get the correct extension and the date:
day = date.split(" ")[0]
time = date.split(" ")[1].replace(':', '-')
filename = f'memories/{day}_{time}.mp4' if type == 'VIDEO' else f'memories/{day}_{time}.jpg'
And then write it to file:
with open(filename, 'wb') as f:
f.write(file.content)
I've made a bot to download all memories.
You can download it here
It doesn't require any additional installation, just place the memories_history.json file in the same directory and run it. It skips the files that have already been downloaded.
Short answer
Download a desktop application that automates this process.
Visit downloadmysnapchatmemories.com to download the app. You can watch this tutorial guiding you through the entire process.
In short, the app reads the memories_history.json file provided by Snapchat and downloads each of the memories to your computer.
App source code
Long answer (How the app described above works)
We can iterate over each of the memories within the memories_history.json file found in your data download from Snapchat.
For each memory, we make a POST request to the URL stored as the memories Download Link. The response will be a URL to the file itself.
Then, we can make a GET request to the returned URL to retrieve the file.
Example
Here is a simplified example of fetching and downloading a single memory using NodeJS:
Let's say we have the following memory stored in fakeMemory.json:
{
"Date": "2022-01-26 12:00:00 UTC",
"Media Type": "Image",
"Download Link": "https://app.snapchat.com/..."
}
We can do the following:
// import required libraries
const fetch = require('node-fetch'); // Needed for making fetch requests
const fs = require('fs'); // Needed for writing to filesystem
const memory = JSON.parse(fs.readFileSync('fakeMemory.json'));
const response = await fetch(memory['Download Link'], { method: 'POST' });
const url = await response.text(); // returns URL to file
// We can now use the `url` to download the file.
const download = await fetch(url, { method: 'GET' });
const fileName = 'memory.jpg'; // file name we want this saved as
const fileData = download.body; // contents of the file
// Write the contents of the file to this computer using Node's file system
const fileStream = fs.createWriteStream(fileName);
fileData.pipe(fileStream);
fileStream.on('finish', () => {
console.log('memory successfully downloaded as memory.jpg');
});
I need to have predefined scripts, accessible from chrome content_script, that could be updated automatically from given URL.
Exactly what i do:
I have content_script.js. Inside it, i`d like to create iframe for current page from predefined html+css+js.Sometimes html or css or js can be changed. I want to avoid updating extension, instead, each time user have internet, he could load fresh html+css+js for further offline usage.
So, how to read and write some internal files within extension from content script (or delegate this task to background script)?
You can use HTML5 Filesystem to have a read/write place for files, or just store it as strings in chrome.storage (with "unlimitedStorage" permission as needed) for later reuse.
This code can then be executed in a content script using executeScript, or, if you enable 'unsafe-eval' for the extension CSP, in the main script (which is dangerous, and should be avoided in most cases).
Note that this Filesystem API has a warning that's it's only supported in Chrome, but that shouldn't be a problem (Firefox / WebExtensions platform explicitly reject self-update mechanisms).
You can do read extension file contents, but you can't write to extension folder since it is sandboxed.
To read an extension file, you can just send Ajax call using chrome.runtime.getURL("filepath") as url
var xhr = new XMLHttpRequest();
xhr.open('GET', chrome.runtime.getURL('your file path'), true);
xhr.onreadystatechange = function() {
if (chr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
var text = xhr.responseText;
// Do what you want using text
}
};
xhr.send();
myappI have to reply with a file in cakePHP3 and in a particular case, it seems that I have a problem, maybe of header.
I want to send an APK (Android package) file.
So if I directly access to the file online, there is no problem but I want to send it from my controller and the file seems to not be considered as a 'raw' apk file.
Here is my code:
public function getmyappapk()
{
$this->request->allowMethod([
'get'
]);
$this->response->type('application/apk');
$this->response->file(WWW_ROOT . DS. 'tmp' .DS. 'app-release.apk',
['download' => true, 'name' => 'MyApp.apk']);
return $this->response;
}
so as I said, if I access to www.mywebsite.com/tmp/app-release.apk, from my smartphone, it downloads it and I can install it.
But if I access to www.mywebsite.com/mycontroller/getmyappapk, it downloads the file and then, tells me that it's impossible to open it.
The type 'application/apk' seems to be ok because if I enter the url in a browser it tells me to record the file recognised as 'android packet'.
But something is certainly missing here.
What is the problem?
I need to launch Chrome from command line with custom parameter, which
contains path to some js-file. Further this path will be used in
extension.
I browsed carefully all related documentation and clicked all nodes in
Chrome debugger, but found nothing which can resemble on command line
parameters. Is it possible anyway to get these parameters or it's need
to write more complex npapi-extension? (theoretically in such npapi-
extension we able to get self process through win-api, command line of
self process and so on).
Hack alert: this post suggests passing a fake URL to open that has all the command-line parameters as query string parameters, e.g.,
chrome.exe http://fakeurl.com/?param1=val1¶m2=val2
Perhaps pass the path to your extension in a custom user agent string set via the command line. For example:
chrome.exe --user-agent='Chrome 43. My path is:/path/to/file'
Then, in your extension:
var path = navigator.userAgent.split(":");
console.log(path[1])
Basically I use the technique given in #dfrankow's answer, but I open 127.0.0.1:0 instead of a fake URL. This approach has two advantages:
The name resolution attempt is skipped. OK, if I've chosen the fake URL carefully to avoid opening an existing URL, the name resolution would fail for sure. But there is no need for it, so why not just skip this step?
No server listens on TCP port 0. Using simply 127.0.0.1 is not enough, since it is possible that a web server runs on the client machine, and I don't want the extension to connect to it accidentally. So I have to specify a port number, but which one? Port 0 is the perfect choice: according to RFC 1700, this port number is "reserved", that is, servers are not allowed to use it.
Example command line to pass arguments abc and xyz to your extension:
chrome "http://127.0.0.1:0/?abc=42&xyz=hello"
You can read these arguments in background.js this way:
chrome.windows.onCreated.addListener(function (window) {
chrome.tabs.query({}, function (tabs) {
var args = { abc: null, xyz: null }, argName, regExp, match;
for (argName in args) {
regExp = new RegExp(argName + "=([^\&]+)")
match = regExp.exec(tabs[0].url);
if (!match) return;
args[argName] = match[1];
}
console.log(JSON.stringify(args));
});
});
Console output (in the console of the background page of the extension):
{"abc":"42","xyz":"hello"}
You could try:
var versionPage = "chrome://version/strings.js";
$.post(versionPage, function(data){
data = data.replace("var templateData = ", "");
data = data.slice(0, -1);
var jsonOb = $.parseJSON(data);
alert(jsonOb.command_line);
});
This assumes you are using jQuery in your loading sequence, you could always substitute with any other AJAX method
Further to the answers above about using the URL to pass parameters in, note that only Extensions, not Apps, can do this. I've published a Chrome Extension that just intercepts the URL and makes it available to another App.
https://chrome.google.com/webstore/detail/gafgnggdglmjplpklcfhcgfaeehecepg/
The source code is available at:
https://github.com/appazur/kiosk-launcher
for Wi-Fi Public Display Screens