I'm using Flask with send_file()
to have people download a file off the server.
My current code is as follows:
@app.route('/', methods=["GET", "POST"])
def index():
if request.method == "POST":
link = request.form.get('Link')
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info_dict = ydl.extract_info(link, download=False)
video_url = info_dict.get("url", None)
video_id = info_dict.get("id", None)
video_title = info_dict.get('title', None)
ydl.download([link])
print("sending file...")
send_file("dl/"+video_title+".f137.mp4", as_attachment=True)
print("file sent, deleting...")
os.remove("dl/"+video_title+".f137.mp4")
print("done.")
return render_template("index.html", message="Success!")
else:
return render_template("index.html", message=message)
The only reason I have .f137.mp4
added is because I am using AWS C9 to be my online IDE and I can't install FFMPEG to combine the audio and video on Amazon Linux. However, that is not the issue. The issue is that it is not sending the download request.
Here is the console output:
127.0.0.1 - - [12/Dec/2018 16:17:41] "POST / HTTP/1.1" 200 -
[youtube] 2AYgi2wsdkE: Downloading webpage
[youtube] 2AYgi2wsdkE: Downloading video info webpage
[youtube] 2AYgi2wsdkE: Downloading webpage
[youtube] 2AYgi2wsdkE: Downloading video info webpage
WARNING: You have requested multiple formats but ffmpeg or avconv are not installed. The formats won't be merged.
[download] Destination: dl/Meme Awards v244.f137.mp4
[download] 100% of 73.82MiB in 00:02
[download] Destination: dl/Meme Awards v244.f140.m4a
[download] 100% of 11.63MiB in 00:00
sending file...
file sent, deleting...
done.
127.0.0.1 - - [12/Dec/2018 16:18:03] "POST / HTTP/1.1" 200 -
Any and all help is appreciated. Thanks!
You need to return
the result of send_file
:
@app.route('/', methods=["GET", "POST"])
def index():
if request.method == "POST":
link = request.form.get('Link')
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info_dict = ydl.extract_info(link, download=False)
video_url = info_dict.get("url", None)
video_id = info_dict.get("id", None)
video_title = info_dict.get('title', None)
ydl.download([link])
print("sending file...")
return send_file("dl/"+video_title+".f137.mp4", as_attachment=True)
else:
return render_template("index.html", message=message)
Unfortunately, this will make it harder for you to "clean up" after sending the file, so you probably want to do that as part of scheduled maintenance (e.g. run a cron job to delete old downloaded files). See here for more information about the problem.
Extending @Rob Bricheno's answer, if you need to clean up after the request, you can create a deferred method that will execute after the request is complete:
@app.route('/', methods=["GET", "POST"])
def index():
if request.method == "POST":
link = request.form.get('Link')
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info_dict = ydl.extract_info(link, download=False)
video_url = info_dict.get("url", None)
video_id = info_dict.get("id", None)
video_title = info_dict.get('title', None)
ydl.download([link])
print("sending file...")
response = send_file("dl/"+video_title+".f137.mp4", as_attachment=True)
# Create handle for processing display results (non-blocking, excecutes after response is returned)
@flask.after_this_request
def add_close_action(response):
@response.call_on_close
def process_after_request():
try:
print("file sent, deleting...")
os.remove("dl/"+video_title+".f137.mp4")
print("done.")
except Exception as e:
logger.exception(str(e))
return response
else:
return render_template("index.html", message=message)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With