I am trying to create buttons based on the contents of a text file. I have pieced together code I found online to almost get the results I want. I want it to automatically load a predesignated file and create the buttons on page load. Currently it asks for the user to choose a file. I don't want that, I want it to just load a file with a hard coded name and generate the buttons.
I apologize in advance, I have zero JavaScript experience (please be gentile).
document.getElementById('file').onchange = function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function (progressEvent) {
console.log(this.result);
// Parse file by line
var lines = this.result.split('\n');
// Create buttons
for (var line = 0; line < lines.length-1; line++) {
var btn = document.createElement("BUTTON");
var t = document.createTextNode(lines[line]);
btn.appendChild(t);
document.body.appendChild(btn);
}
};
reader.readAsText(file);
};
<input type="file" name="file" id="file">
Web pages are not allowed to read local files from the user's file system without explicit permission. They can however retrieve data from the server they were served from, as well as other servers.
If you're just editing a local web page and don't plan to move it to a server, your computer acts as both the client and the server. So you could use XMLHttpRequest instead of <input type=file> to access the file you need.
If you're loading your page via file:///, you'll need to put your file in the same directory as the web page or in a subdirectory (otherwise the same-origin policy will prevent you from accessing the file).
Related
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 am developing an Add-on for Gmail using AppScript.
My objective is to create something similar to the image below. Any hints?
Problem
File upload in Gmail Add-ons. In short - not exactly. Gmail Add-ons use CardService class to build the Ui - and it doesn't have a file input type, nor any drag-and-drop functionality. But there is a workaround.
Step 1. Create trigger widget
Then, ensure that your Card contains a CardSection with an ImageButton, TextButton or KeyValue widget (KeyValue is deprecated, use DecoratedText) that has an OpenLink action set on them. When using the setUrl(url) method to setup URL to open on widget click, use the current project's URL (when deploying both as WebApp and Add-on) that can be accessed dynamically via ScriptApp.getService().getUrl() call.
Step 2. Create file submit form
In the Add-on project, create an Html file that will handle the file upload. You can use sample one or create your own implementation. the sample file uses FileReader Web API to handle the submitted file (note that client-to-server communication in Google Apps Script requires preventing submit event handler and calling a server-side function via goolge.script.run API only).
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form>
<input name="file" type="file" />
<button id="submit" type="submit">Save file</button>
</form>
<script>
var form = document.forms[0];
form.addEventListener('submit', (event) => {
event.preventDefault();
var file = form.elements[0].files[0];
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = () => {
var buffer = reader.result;
var data = Array.from(new Int8Array(buffer));
google.script.run.withSuccessHandler((server) => {
top.window.close();
}).saveFile(data,file.name,file.type);
};
});
</script>
</body>
</html>
Step 3. Setup doGet()
In your WebApp code, add the required doGet() function that will show the file upload form that we created during step 2. It can be as simple as a couple lines of code (just make sure to return the html file parsed by HtmlService):
function doGet() {
var html = HtmlService.createHtmlOutputFromFile('file name from step 2');
return html;
}
Step 4. Handle file upload
In your WebApp code, add handler that will receive file data (this sample assumes you read it as byte[], see step 2 for details).
function saveFile(upload,name,mime) {
var blob = Utilities.newBlob(upload,mime,name);
var file = DriveApp.createFile(blob);
Logger.log(file.getUrl()) //test upload;
//handle file as needed;
return;
}
Step 5. Deploy as WebApp
Lastly, you will have to deploy your Add-on as both WebApp (or bundle with one) and an Add-on. Assuming you've already configured manifest for the Add-on, go to "Publish" menu, select "Deploy as web app", create a deployment and allow access to anyone.
Notes
This method won't allow you to easily update the Ui to show which files were uploaded, but you can add a withSuccessHandler() call to google.script.run that on successful server-side handling of the uploaded file closes the window with the form, save state info to cache / user properties. Then, if you set the OpenLink's OnClose property to RELOAD_ADD_ON (see step 1), you will be able to conditionally update Ui to notify the user of successful upload.
UPDATE: after Tanaike's comment I reworked the upload process to better handle files: changed binary string file read to ArrayBuffer transformed to Int8Array and uploaded as an Array instance.
Current issue is the .g* files upload (despite correct transfer). Will update the answer when solved.
References
OpenLink class reference;
FileReader Web API reference on MDN;
newBlob() method reference (Utilities class);
Client-to-server communication in GAS guide;
Creating and serving HTML in GAS guide;
Web Apps guide;
Here's my code:
function myFunction() {
var url = "https://cdn-04.anonfile.com/t3ScWad7b9/fc36c282-1522257874/CRASH_FILES__2018.03.24.14.06.27_.zip";
var blob = UrlFetchApp.fetch(url).getBlob();
GmailApp.sendEmail("derekantrican#gmail.com", "", "", {attachments: [blob]});
}
As you can see, the function gets a file (a .zip) from the url and attaches it to an email that it then sends. The problem is that Google's servers are blocking the .zip:
"Learn more" leads here: https://support.google.com/mail/answer/6590?hl=en
This .zip (you can download from the URL yourself) only contains two .log files and a .xml file - none of which are banned on the url above.
I've also tried uploading to Google Drive first, then sending:
function myFunction(){
var url = "https://cdn-04.anonfile.com/t3ScWad7b9/fc36c282-1522257874/CRASH_FILES__2018.03.24.14.06.27_.zip";
var zipBlob = UrlFetchApp.fetch(url).getBlob();
zipBlob.setContentType("application/zip");
var file = DriveApp.createFile(zipBlob);
GmailApp.sendEmail("derekantrican#gmail.com", "", "", {attachments: [file.getBlob()]});
}
Same result. Any other suggestions?
Have you actually checked the contents of the 'zip' file that gets saved to your Google Drive? The issue is probably due to you attaching an HTML page, not the zip file. The link you provided is for the landing page, not the download itself, so the content of the page is exactly what is being served back when you call UrlFetchApp.fetch().
Here's what was saved to my Google Drive after sending a 'GET' request to your link:
The page requires a user to manually click on the button to initiate the download. There are no redirects, so you can't get the file by using this pattern:
UrlFetchApp.feth(url, {followRedirects: true});
The question is, can you get the actual link to the file? Well, kind of. In Chrome, open your downloads page by pressing Ctrl + J (Windows) or CMD + Shift + J (MacOS). The URLs displayed next to file names are the actual direct links to the files. However, these are very short-lived and expire within seconds.
You can grab the link and quickly paste it inside your code to make sure it works
var blob = UrlFetchApp.fetch(url).getBlob();
Logger.log(blob.getContentType()); //logs 'application/zip'
Logger.log(blob.getName()); // logs CRASH_FILES__2018.03.24.14.06.27_.zip
DriveApp.createFile(blob);
Result (note that it stops working after a few seconds as the new unique link is generated by the server):
We are using Firebase Google Cloud Storage Bucket to store our files.
When the logged in user wants the download the file kept inside certain folder
Eg: 123/admin/1469611803143/123.xlsx
The url generated will be
https://firebasestorage.googleapis.com/v0/b/MYWEBSITE.appspot.com/o/123%2Fadmin%2F1469611803143%2F123.xlsx?alt=media&token=whatever_alpa_numeric_token
As I download this file the file name will be 123%2Fadmin%2F1469611803143%2F123.xlsx
and not 123.xlsx
We have tried using download attribute to change the file name
but this did not change the file name to 123.xlsx
Please HELP
I'm pretty new with firebase but I achieved this with the following code :
var storageRef = firebase.storage().ref();
var child = storageRef.child("your path");
var uploadTask = child.put(<file>);
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
function(snapshot){
// HANDLE TASK PROGRESS
},
function(error){
// HANDLE ERROR
},
function(){
// UPLOAD SUCCESSFULL
var newMetadata = {
contentDisposition : "attachment; filename=" + fileName
}
child.updateMetadata(newMetadata)
})
This is (fortunately or unfortunately) intended behavior. Technically, files in Firebase Storage are stored with the full path (so 123%2Fadmin%2F1469611803143%2F123.xlsx is actually the file name--the slashes and percent escaping are part of the name, and are only represented as path separators in the UI), which is how we get this behavior.
We're likely to modify how downloads work in the future (in that we'll truncate the name), but we've been busy fixing other bugs and polishing higher priority pieces.
i want to save a dropped image into the html5 filesystem. The problem is that i do not know how to write binary data into the file system with the file api. Below are parts of my code:
var reader = new FileReader();
reader.onloadend = function(e)
{
var data = e.target.result;
// Open File System code (Codes Omitted)
// Create file (Codes Omitted)
fileEntry.createWriter(function(fileWriter)
{
// This is the problem, the file is create, something is written to the file
// because the size is exact same with the dragged file (image). But when i
// try to view the file (image), it displays nothing.
var bb = new WebKitBlobBuilder
bb.append(data);
fileWriter.write(bb.getBlob(""));
}
}
reader.readAsBinaryString(cur_file);
I intentionally left out some codes like the file system and file creation. I only need help with saving binary data.
Thanks.
I've encounter a similar issue
Since you didn't parse your code here,I assume that you read the image in a wrong way,
maybe
You read the cur_file as binary string,Did your fileReader read it by readAsText method
Since the file stores binaryString,If your fileReader read it by another way,e.g readAsDataURL,that means you encode it again,so you couldn't get the right answer