Consecutive downloads to browser in Javascript - javascript

I am using this common method to download a file in javascript:
var URI = //some uri
var dl = document.createElement('a');
dl.href = URI;
dl.download = 'file name';
document.body.appendChild(dl);
download_link.click();
document.body.removeChild(dl);
When I execute it the first time it works, but fails for the next downloads. Do you know why this is? Thanks

Trying to run your code for the second time, Chrome shows this message:
My browser is in pt-BR, the translation is as follows:
http://stackoverflow.com would like to:
* Download multiple files
[Allow] [Block]
If you block it, it will not download the next files. You can check your current permission settings by click in the (i) icon before the URL and looking for automatic downloads. The default only downloads once.

Related

Tampermonkey To open multiple javascript in href in new tab [duplicate]

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');
});

<a> element does not recognize the file extension automatically when downloading a file

I'm currently developing an application where the user clicks on an element, that element calls a JS function and the function handles a file download.
The files are reports generated dynamically by Devexpress XtraReports module, converted to Base64 and then sent back to the client side. When the client receives the Base64 string, the JS function creates an <a> element, sets the href attribute to data:application/pdf;base64,JVBERi0xLjQNCiWio[...] and simulates a click with the click() event.
Here's the piece of JS code that handles the file download:
let downloadLink;
try {
downloadLink = executionId ? await getLinkPdfBase64(executionId) : false;
} catch (error) {
downloadLink = false;
console.log(error);
}
if (downloadLink) {
const aElement = document.createElement("a");
downloadLink = "data:application/pdf;base64," + downloadLink;
aElement.setAttribute("download", currentReportData.LayoutName);
aElement.setAttribute("href", downloadLink);
aElement.click();
aElement.remove();
} else {
DevExpress.ui.dialog.alert( //Ignore this, it's a Devexpress component
"Your report could not be generated",
"Alert"
);
}
The problem is:
When I generate a report with custom parameter types, Devexpress generates it correctly (the Base64, if converted to string, is visibly correctly formed) but the browser (Google Chrome) downloads the file with the extension ".0".
If the report has normal Devexpress parameters (like Strings, Int32, Guids, etc)) the file is downloaded with the correct ".pdf" extension.
Here's a picture of a correctly downloaded PDF and a ".0" extension file:
Could it be the JS function the cause or the solution to the problem? If not, almost for sure there will be something wrong with the report generator (Devexpress).
NB: If I manually change the ".0" extension to ".pdf" the file opens and it is displayed / formed correctly.
Turns out I ended up solving it just by adding the file extension ".pdf" in the download attribute, so when the browser can't recognize it, you are already specifying which one it is:
aElement.setAttribute("download", currentReportData.LayoutName + ".pdf");

Making Firefox and Chrome download image under a specific name

Given https://www.example.com/image-list:
...
<a href="/image/1337">
<img src="//static.example.com/thumbnails/86fb269d190d2c85f6e0468ceca42a20.png"/>
</a>
<a href="//static.example.com/full/86fb269d190d2c85f6e0468ceca42a20.png"
download="1337 - Hello world!.png">
Download
</a>
...
This is a user script environment, so I have no access to server configuration. As such:
I can't make server accept user-friendly file names like https://static.example.com/full/86fb269d190d2c85f6e0468ceca42a20 - 1337 - Hello World!.png.
I can't configure Cross-Origin Resource Sharing. www.example.com and static.example.com are separated by CORS wall by design.
How to make Firefox and Chrome display Save File As dialog with the suggested file name "1337 - Hello world!.png" when a user clicks on the "Download" link?
After some failing and googling, I learned these problems:
Firefox completely ignores existence of the download attribute on some image MIME types.
Firefox completely ignores existence of the download attribute on cross-site links.
Chrome completely ignores value of the download attribute on cross-site links.
All these points don't make any sense to me, all look like "let's put random non-sensical limitations on the feature", but I have to accept them as it's my environment.
Do any ways to solve the problem exist?
Background: I'm writing a user script for an image board which uses MD5 hashes as file names. I want to make saving with user-friendly names easier. Anything which gets me closer to this would be helpful.
I guess I can get around the limitations by using object URLs to blobs and a local proxy with hacked CORS headers, but this setup is obviously beyond reasonable. Saving through canvas could work (are images "protected" by CORS in this case too?), but it will either force double lossy compression or lossy-to-lossless conversion, given JPEG files, neither of which are good.
All modern browsers will ignore the download attribute in the anchor tag for cross-origin URL'S.
Reference : https://html.spec.whatwg.org/multipage/links.html#downloading-resources
According to the spec makers, this represents a security loophole as a user could be tricked into downloading malicious files while browsing a secure site, believing that the file is also originating from the same secure site.
Any interesting conversation for implementing this feature in the firefox browser can be found here : https://bugzilla.mozilla.org/show_bug.cgi?id=676619
[ Edit by Athari ]
Quote from specification:
This could be dangerous, because, for instance, a hostile server could be trying to get a user to unknowingly download private information and then re-upload it to the hostile server, by tricking the user into thinking the data is from the hostile server.
Thus, it is in the user's interests that the user be somehow notified that the resource in question comes from quite a different source, and to prevent confusion, any suggested filename from the potentially hostile interface origin should be ignored.
Clarification on the mysterious scenario:
the more serious issue with CORS downloads is if a malicious site forces a download of a file form a legitimate site and some how gets access to its content. so lets say I download the user gmail inbox page and explore its messages.
in this case an evil site will have to fool the user into downloading the file and uploading it back to the server, so lets say we have a gmail.com/inbox.html actually contains all the user mail messages and the attacker sites offers a download link for a coupon file, that should be uploaded to another evil site. the coupon will supposedly offer a 30% discount on a new Ipad. the download link will actually point to gmail.com/inbox.html and will download it as "30off.coupon", the if the user will download this file and upload it without checking it's content the evil site will get the user "coupon" and so its inbox content.
Important notes:
Google originally didn't limit download attribute by CORS and was explicitly against this. It was later forced to adjust Chrome implementation.
Google was opposed to using CORS for this.
Alternative solutions were proposed with giving a user a warning about cross-origin downloads. They were ignored.
Well there can be notification or deny/allow mechanism when downloading from another origin (e.g. like in case of geolocation API). Or not to send cookies in case of cross origin request with download attribute.
Some developers do share the opinion that the restriction is too strong, severely limits the usage of the feature and that the scenario is so complicated that the user who would do this would easily download and run an executable file. Their opinion was disregarded.
The case against allowing cross-origin downloads is centered around the premise that visitors of an [evil] site (eg, discountipads.com) could unknowingly download a file from a site containing their own personal information (eg, gmail.com) and save it to their disk using a misleading name (eg, "discount.coupon") AND THEN proceed to another malicious page where they manually upload that same file they just downloaded. This is quite far-fetched in my opinion, and anyone who would succumb to such trivial trickery perhaps does not belong online in the first place. I mean c'mon...Click here to download our special discount offer and then re-upload it through our special form! Seriously? Download our special offer and then email it to this Yahoo address for a big discount! Do the people who fall for these things even know how to do email attachments?
I'm all for browser security, but if the good people of Chromium have no problem with this I don't see why Firefox has to completely banish it. At the very least I'd like to see a preference in about:config to enable cross-origin #download for "advanced" users (default it to false). Even better would be a confirmation box similar to: "Although this page is encrypted, the information you submit through this form won't be" or: "This page is requesting to install addons" or: "Files downloaded from the web may harm your computer" or even: "The security certificate of this page is invalid" ...y'know what I mean? There are myriad ways to heighten the user's awareness and inform them this might not be safe. One extra click and a short (or long?) delay is enough to let them assess the risk.
As the web grows, and the use of CDNs grows, and the presence of advanced web-apps grows, and the need to manage files hosted across servers grows, features like #download will become more important. And when a browser like Chrome supports it fully whereas Firefox does not, this is not a win for Firefox.
In short, I think that mitigating the potential evil uses of #download by simply ignoring the attribute in cross-origin scenarios is a woefully ill-thought move. I'm not saying the risk is entirely non-existent, quite the contrary: I am saying there are plenty of risky things one does online in the course of his day...downloading ANY file is high among them. Why not work around that issue with a well-thought user experience?
Overall, considering widespread use of CDNs and intentionally putting user-generated content on a different domain, the primary use for the download attribute is specifying a file name for blob downloads (URL.createObjectURL) and the like. It can't be used in a lot of configurations and certainly not very useful in user scripts.
Try something like:
Get the external image to your server first
Return the fetched image from your server.
Dynamically create an anchor with download name and .click() it!
while the above was just a pretty short tips list... give this a try:
on www.example.com place a fetch-image.php with this content:
<?php
$url = $_GET["url"]; // the image URL
$info = getimagesize($url); // get image data
header("Content-type: ". $info['mime']); // act as image with right MIME type
readfile($url); // read binary image data
die();
or with any other server-side language that achieves the same.
The above should return any external image as it's sitting on your domain.
On your image-list page, what you can try now is:
<a
href="//static.example.com/thumbnails/86fb269d190d2c85f6e0468ceca42a20.png"
download="1337 - Hello world!.png">DOWNLOAD</a>
and this JS:
function fetchImageAndDownload (e) {
e.preventDefault(); // Prevent browser's default download stuff...
const url = this.getAttribute("href"); // Anchor href
const downloadName = this.download; // Anchor download name
const img = document.createElement("img"); // Create in-memory image
img.addEventListener("load", () => {
const a = document.createElement("a"); // Create in-memory anchor
a.href = img.src; // href toward your server-image
a.download = downloadName; // :)
a.click(); // Trigger click (download)
});
img.src = 'fetch-image.php?url='+ url; // Request image from your server
}
[...document.querySelectorAll("[download]")].forEach( el =>
el.addEventListener("click", fetchImageAndDownload)
);
You should see finally the image downloaded as
1337 - Hello world!.png
instead of 86fb269d190d2c85f6e0468ceca42a20.png like it was the case.
Notice: I'm not sure about the implications of simultaneous requests toward fetch-image.php - make sure to test, test.
If you have access to both, backend and frontend code, here are steps which could help you
I'm not sure which type of backend language you are using, so I will just explain what need to be done without code sample.
In backend, for preview your code should work as is, if you get in query string something like ?download=true then your backend should pack file as dispositioned content, in other words you would use content-disposition response header. This will open you possibility to put additional attributes to content, like filename, so it could be simething like this
Content-Disposition: attachment; filename="filename.jpg"
Now, in frontent, any link which should behave as download button need to contain ?download=true in href query parameter AND target="_blank" which will temporary open another tab in browser for download purpose.
<a href="/image/1337">
<img src="//static.example.com/thumbnails/86fb269d190d2c85f6e0468ceca42a20.png"/>
</a>
<a href="//static.example.com/full/86fb269d190d2c85f6e0468ceca42a20.png?download=true" target="_blank" title="1337 - Hello world!.png">
Download Full size
</a>
I know that this works without CORS setup and if user clicks on download link, but I never tested Save As dialog in browser... and it will take some time to build this again, so please give it a try.
Relevant Chromium API...
https://developer.chrome.com/extensions/downloads#event-onDeterminingFilename
Example...
chrome.downloads.onDeterminingFilename.addListener(function(item,suggest){
suggest({filename:"downloads/"+item.filename}); // suggest only the folder
suggest({filename:"downloads/image23.png"}); // suggest folder and filename
});
Oops... you're on server side but I assumed client side! I'll leave this here though in case someone needs it.
You can try to do this
var downloadHandler = function(){
var url = this.dataset.url;
var name = this.dataset.name;
// by this you can automaticaly convert any supportable image type to other, it is destination image format
var mime = this.dataset.type || 'image/jpg';
var image = new Image();
//We need image and canvas for converting url to blob.
//Image is better then recieve blob through XHR request, because of crossOrigin mode
image.crossOrigin = "Anonymous";
image.onload = function(oEvent) {
//draw image on canvas
var canvas = document.createElement('canvas');
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
canvas.getContext('2d').drawImage(this, 0, 0, canvas.width, canvas.height);
// get image from canvas as blob
var binStr = atob( canvas.toDataURL(mime).split(',')[1] ),
len = binStr.length,
arr = new Uint8Array(len);
for (var i = 0; i < len; i++ ) {
arr[i] = binStr.charCodeAt(i);
}
var blob = new Blob( [arr], {type: mime} );
//IE not works with a.click() for downloading
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, name);
} else {
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = name;
a.click();
}
};
image.src = url;
}
document.querySelector("[download]").addEventListener("click", downloadHandler)
<button
data-name="file.png"
data-url="https://tpc.googlesyndication.com/simgad/14257743829768205599"
data-type="image/png"
download>
download
</button>
Another modern way for modern browsers (except Internet Explorer)
var downloadHandler = function(){
var url = this.dataset.url;
var name = this.dataset.name;
fetch(url).then(function(response) {
return response.blob();
}).then(function(blob) {
//IE and edge not works with a.click() for downloading
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, name);
} else {
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = name;
a.click();
}
});
};
document.querySelector("[download]").addEventListener("click", downloadHandler)
<button
data-name="file.png"
data-url="https://tpc.googlesyndication.com/simgad/14257743829768205599"
download>
download
</button>
I'm able to rename base64 images with a save as input field.
I think your best bet is to create your own "save as" box. When a user clicks "download", display a "File Name: {input field}" and a save button. Have the save button change filename and then call the download function.
function save2() {
var gh = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRFAAAAPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09EvTTBAAAABB0Uk5TAA8fLz9PX29/j5+vv8/f7/rfIY4AAARsSURBVHja7VvZkusqDAyrAQvQ/3/teZjExrHDZoGrbl0/z0RtLY1oya/X/8+Nh/NHzYuAGPRz9llERET1GACJiIgYngaAkmvNnwTgERHtgwDefngawDofgDkAwPlp4I4AzHQA/gggstk0jF/P7ELQ3wBQPBoBRPRzTyI8P/bBGvh79FMstFXCvDSAt0kHzyBYNv7jj/iAx48DEiwzEfj0AFi/EEw4F+2B/5mfXQsbB4ZDQOKGwM2ioE+4hUdEm3jCjzybRbw4gIXkrxfbySnqCfYhS48rG23fs/wRGYdcGIQv1PsOcIgTkp//xTcs4WbyTEjs67pmFfh8+3+X1s0Jy3z7rxezaZ9EdTjI2MC1MpA37LqN65kjdoJuPmtUUpC40NmvLy2WntM3OcH09RupE8KdMLjefufgBE1gvz2blnj/2pDY7wikSPold9M+dCVSWpDuln1HUMLuCfsHEndP2H+9uO+kJEfVaicNq+zin9udxY6gQcrRlFeNHUG1oCfpjpIjAtmaukQXHRabpJwdMNlFSzZFdL3Dv4WkrlH4lyH6Y6jOgj0BSPUGWV0InrQAztISr2UgahFe1r3XJgHRC9C+qhK3CqC/4H6Sm1XV64ApCKt5NegOgFTGGGPMIlnhx22NA64zhUsppTxVMtcuvY5hcCqX31DhgAu+EgZ+WLjSjoPJvF6mBH5lIFvC7wHBJ7kAAAByjFdkAvdDg0o7/PPByiOCSSIvbfhBo6HExvES/ftwjOs7v7iyoZCl0qhMhHWpDQoX9QvH/xJd+osriAbr9ZktEQONCm3yAD5EEU833YWIlgsA1PD5UwGAGz4DLAAIw0eAeQBs/CTaZi2o8VNYyAIwP2qAHsCSZYGR6xD5xtgPTwGeBzB+I0Xlj+Oajo2kCEK+GRqfg2sWwEAaKhCNLDdsRCkgnwLg8kEeDyDmLQwHoAp3w+EA1kJPPBoAL6lEYnAZmuLtfCwRbToZLwEYNP7X5Vs33NEFuI15BS6U7+auuydmGkoKXI1Kt9RlIZPHIIllLbfzWwboCm2AF480b7WUQkipDWySkhPlg7ggU9apWPFqkWzV2TZC1Am1a1UMltMWW8F6Xve4qpRCX86U3ZQkcEtFF79UKtW8RSJnsvr+IDK7N23HRScH+mrtWQ/RCF3D+DYOaM337bOKftvQ78iKps3fjbDIrkeX22cVLqAKAovVFfD1DzRi/V4AgbWmDMW8ivmO7Qto9FlV/FvGr5xsZilj3/hXI00UTPcKi6PYgkrXR5qnb/72ZuRho03fSF5E1xOGg7qvb5VPz2akTmcbnT48LExDCysycxitdGfRcWUbar2gvj59cDfqyH3NoMpNyt+k5r77t1B+tb/eZNzJtTt1y+4umXM49b9g1AmFUPvloDdzqsppDweA/RuSOoDLv6D7GvRAKPUP5ceo3DWbX4nFXm5iy8ubEfqCWiut22HDDqZcyBuP6zL6s0euLVzbBqunfWbFpTZmhfdjjVFy9seO/6nnH0Mpp/3TjvofAAAAAElFTkSuQmCC"
var a = document.createElement('a');
a.href = gh;
a.download = document.getElementById("input").value;
a.click()
}
Filename: <input id="input" name="input" placeholder="enter image name"></insput><button onclick="save2()">Save</button>
The above code will let you name the file for the user If you want the user to be able to name the file himself then you need to create an input field that updates a.download = 'imagetest.png'; through a listening function or onkeychange. I got it to work through "a.download = document.getElementById("input").value;". It's amazing what getElementByID can do.
Browsers are very limited in the ability to name files for people to download. I imagine it's a lack of functionality that has been overlooked.
If you want to take it a step further you can hide the "file name:" input field with display:hidden;. And you can have a "download" button with an onclick function that sets the "file name: input / save" div to no longer set to display:hidden;. This can also be done through getelementbyID.
I did however notice that there seems to be an issue with renaming the image with a URL instead of base64. So I tried integrating my code with yours though none of the code below seemed to work properly when clicking on your download link. I still think it's close enough that you may want to fiddle around with it if this is the route you want to go:
<script>
function save2() {
var gh = "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"
var a = document.createElement('a');
a.href = gh;
a.download = document.getElementById("input").value;
a.click()
}
function downloadit(){
var x = document.getElementById("input").value;
document.getElementById("dl").getAttribute("download") = x;
}
document.getElementById("dl").onclick = function() {
document.getElementById("dl").download= a.download = document.getElementById("input").value;
return false;
}
</script>
<a href="/image/1337">
<img src="//static.example.com/thumbnails/86fb269d190d2c85f6e0468ceca42a20.png"/>
</a>
<a onclick='downloadit()' id="dl" href="//static.example.com/full/86fb269d190d2c85f6e0468ceca42a20.png"
download="1337 - Hello world!.png">
Download
</a>
Filename: <input id="input" name="input" placeholder="enter image name"></insput><button onclick="save2()">Save</button>
Lastly, I was able to rename your example.com image with the following script. Though when I try it with a working googleimage it doesn't seem to rename. So you might want to dabble with this as well.
document.getElementById("dl").onclick = function() {
document.getElementById("dl").download=document.getElementById("input").value;
}
Filename: <input id="input" name="input" placeholder="enter image name"></input>
<a id="dl" href="//static.example.com/full/86fb269d190d2c85f6e0468ceca42a20.png"
download="1337 - Hello world!.png">
Download
</a>

encodeURI file download - crashing browser

I created a web application to clean up CSV/TSV data. The app allows me to upload a CSV file, read it, fix data, and then download a new CSV file with the correct data. One challenge I have run into is downloading files with more than ~ 2500 lines. The browser crashes with the following error message:
"Aw, Snap! Something went wrong while displaying this webpage..."
To work around this I have changed the programming to download multiple CSV files not exceeding 2500 lines until all the data is downloaded. I would then put together the downloaded CSV files into a final file. That's not the solution I am looking for. Working with files of well over 100,000 lines, I need to download all contents in 1 file, and not 40. I also need a front-end solution.
Following is the code for downloading the CSV file. I am creating a hidden link, encoding the contents of data array (each element has 1000 lines) and creating the path for the hidden link. I then trigger a click on the link to start the download.
var startDownload = function (data){
var hiddenElement = document.createElement('a');
var path = 'data:attachment/tsv,';
for (i=0;i<data.length;i++){
path += encodeURI(data[i]);
}
hiddenElement.href = path;
hiddenElement.target = '_blank';
hiddenElement.download = 'result.tsv';
hiddenElement.click();
}
In my case the above process works for ~ 2500 lines at a time. If I attempt to download bigger files, the browser crashes. What am I doing wrong, and how can I download bigger files without crashing the browser? The file that is crashing the browser has (12,000 rows by 48 columns)
p.s. I am doing all of this in Google Chrome, which allows for file upload. So the solution should work in Chrome.
I've experienced this problem before and the solution I found was to use Blobs to download the CSV. Essentially, you turn the csv data into a Blob, then use the URL API to create a URL to use in the link, eg:
var blob = new Blob([data], { type: 'text/csv' });
var hiddenElement = document.createElement('a');
hiddenElement.href = window.URL.createObjectURL(blob);
Blobs aren't supported in IE9, but if you just need Chrome support you should be fine.
I also faced same problem. I used this code,it will works fine. You can also try this.
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(new Blob([base64toBlob($.base64.encode(excelFile), 'text/csv')]),'data.csv');
} else {
var link = document.createElement('a');
link.download = 'data.csv';
// If u use chrome u can use webkitURL in place of URL
link.href = window.URL.createObjectURL(new Blob([base64toBlob($.base64.encode(excelFile), 'text/csv')]));
link.click();
}

Upload file to Windows Azure with only the link of the file is provided

How can I upload a file in azure if I only have the URL of the file to upload. In this case, i 'm using Dropbox file chooser which selects file from dropbox and returns its url path.
eq
https://www.dropbox.com/s/o9myet72y19iaan/Getting%20Started.pdf
Now we need the file to be stored in Windows Azure blob. What is the easiest way to do this without downloading the file first.
I'm planning to use a asp.net web api for the uploading of file to azure blob.
At first, I thought it should be quite straight forward as Azure Blob Storage support copying blobs from external URL however I don't think this would work in case of Dropbox files. I just tried it and got an error even though.
The link you mentioned above is not the direct link to the file. It's a link to a page on Dropbox's website from where you can download a file. This is obviously you don't want. Here's an alternate solution which you can try:
Replace www.dropbox.com in your URL with dl.dropboxusercontent.com (based on #smarx's comments below) and use that URL in the following code:
First you would need to append dl=1 to your request URL as query string. So your Dropbox URL would be https://www.dropbox.com/s/o9myet72y19iaan/Getting%20Started.pdf?dl=1. dl query string parameter indicates the file needs to be downloaded.
Next, using HTTPWebRequest try accessing this URL. Dropbox will respond back with another link and 302 status code. This link would be something like https://dl.dropboxusercontent.com/s/o9myet72y19iaan/Getting%20Started.pdf?token_hash=<tokenhash>.
Use this link in the code below to copy file. This would work.
CloudStorageAccount acc = new CloudStorageAccount(new StorageCredentials("account", "key"), false);
var client = acc.CreateCloudBlobClient();
var container = client.GetContainerReference("container-name");
container.CreateIfNotExists();
var blob = container.GetBlockBlobReference("dropbox-file-name");
blob.StartCopyFromBlob(new Uri("dropbox URL with dl.dropboxusercontent.com"));
Console.WriteLine("Copy request accepted");
Console.WriteLine("Now checking for copy state");
bool continueLoop = true;
do
{
blob.FetchAttributes();
var copyState = blob.CopyState;
switch (copyState.Status)
{
case CopyStatus.Pending:
Console.WriteLine("Copy is still pending. Will check status again after 1 second.");
System.Threading.Thread.Sleep(1000);//Copy is still pending...check after 1 second
break;
default:
Console.WriteLine("Terminating process with copy state = " + copyState.Status);
continueLoop = false;
break;
}
}
while (continueLoop);
Console.WriteLine("Press any key to continue.");

Categories