This is probably a super simple question to answer, but I've yet to find an answer to it by searching. How can I provide a link to have a file download? For example, if I had a document on my webpage, and someone wanted a copy of it, they would click on the link and it would download. How difficult is that to implement? Thanks!
Videos
In modern browsers that support HTML5, the following is possible:
<a href="link/to/your/download/file" download>Download link</a>
You also can use this:
<a href="link/to/your/download/file" download="filename">Download link</a>
This will allow you to change the name of the file actually being downloaded.
This answer is outdated. We now have the
downloadattribute. (see also this link to MDN)
If by "the download link" you mean a link to a file to download, use
<a href="http://example.com/files/myfile.pdf" target="_blank">Download</a>
the target=_blank will make a new browser window appear before the download starts. That window will usually be closed when the browser discovers that the resource is a file download.
Note that file types known to the browser (e.g. JPG or GIF images) will usually be opened within the browser.
You can try sending the right headers to force a download like outlined e.g. here. (server side scripting or access to the server settings is required for that.)
Evidently I was wrong. pythonanywhere is really easy. (But you must use any paid plan in order to access most outside servers (i.e. get files from any website you want)). As of right now, the cheapest plan they have is $5 a month.
Stackoverflow isn't a code-writing service. But enjoy this little exception.
here's a basic implementation of what you've asked for:
We're gonna use an HTTP server written in Python, using a framework called Flask. That server will provide two functions:
- Serve us that basic form you've described
- allow us to request from the backend the file we want, and it will force our web browser to download it (and not display it, for example)
Step 1
Create a "pythonanywhere" account.
Attention: your website will be hosted on username.pythonanywhere.com, choose wisely.
hit "open web tab"*

Step 2
Select the latest Flask version in "add new web app" (3.10 in this case) and hit Next.

Step 3
verify the website works, click on that link, you should see "Hello from Flask!".

Step 4
Go to the "Files" tab, enter the mysite directory

and create a new directory called "templates"

Step 5
Create a new file called index.html,
and put this html in it:
(css and form taken from w3schools)
<!DOCTYPE html>
<html>
<style>
input[type=text], select {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=submit] {
width: 100%;
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type=submit]:hover {
background-color: #45a049;
}
div {
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}
</style>
<body>
<h3>File Proxy</h3>
<div>
<form method="POST" action="/download"> <!-- notice the @app.route("/download"...) in the flask file -->
<label for="fpath">File Path</label>
<input type="text" id="fpath" name="fpath" placeholder="Path...">
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
Hit save
Step 6
Go back to the "Files" tab, and enter mysite directory again.
edit the flask_app.py file

and replace the code in it with the following:
from flask import Flask, request, render_template, Response
import requests
app = Flask(__name__)
content_type_to_extension={"text/html": ".html"}
FALLBACK_EXTENSION=".bin"
# get the path from the form, GET it ourselves, and return it with a content-type that will force the client's browser to download it and not attempt to display it.
@app.route("/download", methods=["POST"])
def loadData():
data = request.form["fpath"]
r = requests.get(data)
response = Response(
r.content,
status=r.status_code,
content_type="application/stream"
# content_type=r.headers['content-type']
)
# basic naming attempt. if it has a uri (text after the last /), let's (maybe falsly, this is a POC) assume that it has a file extension. (you can add regex tests and whatnot)
try:
fname = data.replace('://','')
fname = fname[fname.rindex("/")+1:]
assert (len(fname) > 1)
except (IndexError, ValueError, AssertionError):
fname = data.replace("/", "-")
ext = content_type_to_extension.get(r.headers['content-type'].split(";")[0], FALLBACK_EXTENSION) # if we can't find ther correct extension, fallback to .bin
fname += ext
response.headers["Content-Disposition"] = f'attachment; filename={fname}'
return response
@app.route("/")
def index():
return render_template("index.html") # that html file in /templates
if __name__ == "__main__":
app.run(host='0.0.0.0')
Hit save

Step 7
Go back to the "web" tab, and hit that green "reload" button. (or the blue reload icon next to the save in the flask_app.py edit panel)
And go to your website.
The requests library requires a schema to be specified.
so don't forget the http(s):// or add it via python.

If you don't have a paid account, checking out the error logs in the "web" tab tells us
OSError('Tunnel connection failed: 403 Forbidden')))
**NO MATCH**
or
Network is unreachable
So you gotta go with a paid plan. Or find some other method to host your web server.
For the record - what we're doing here is creating a "dumbed-down" web gui version of a cli http client, like wget or curl.
you could just run in bash / powershell wget <your-url> and it would be basically the same.
This code can work, if you want to download a website on the same domain.
For example, you can download https://example.com/main.html , if your domain is https://example.com/
However, if your domain is https://example2.org/, it is not working.
The reason why you can not download all pages from the internet is the browser is using CORB for safety reason.
<head>
<script src="https://requirejs.org/docs/release/2.3.5/minified/require.js"></script>
</head>
<button type="button" id="down">Download</button>
<input id="InputURL" placeholder="The URL you want to download." style="width:100%">
<p id="HiddenLable" style="">
The HTML
</p>
<script language="javascript">
document.getElementById('down').onclick = function () {
//var filename = "Download.html";
//var content = "Hello, you download a text file by Javasctipt.";
//veiwweb(document.getElementById('InputURL').value);
//var content = document.getElementById("HiddenLable").innerHTML;
//console.log(content);
//download("DownLoad.html", content);
veiwweb(document.getElementById('InputURL').value);
};
function veiwweb(TheLink){
if ( window.ActiveXObject ) // windows
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
else if ( window.XMLHttpRequest ) // other sys
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = Callback;
xmlHttp.open("GET", TheLink, false ); // read
xmlHttp.send(null);
}
function Callback()
{
if ( xmlHttp.readyState == 4 ) {
if ( xmlHttp.status == 200 ) {
var value = xmlHttp.responseText;
document.getElementById("HiddenLable").innerHTML = value;
download("DownLoad.html", value);
}
}
}
function download(filename, content) {
//can not use this function to call viewweb() function because the value may not downloaded yet.
var blob = new Blob([content], {type: 'text/plain'});
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.style = "display: none";
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function () {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 5);
}
</script>
If you tried to download a HTML from a different domain, you can see this in the console:
Access to XMLHttpRequest at 'https://******/' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.