I’m trying to make a private file host and I have it set to return a send_file() when the, for example, /media/someSong.mp3
url is called.
But I want to make it more styled so when you visit /media/someSong.mp3
, instead of your browser trying to play that MP3 in it, it will use a HTML page with a tag that parses the send_file() sent by an argument.
Currently, I have this:
@app.route('/media/<mediaID>') def mediaStuff(mediaID): try: return render_template('parse-it.html', title=title, media_file=send_file(f'./media/{mediaID}')) # return send_file(f'./media/{mediaID}') except FileNotFoundError: return 'The media you tried to view doesn't exist.'
And here is what I have in my templates/parse-it.html
file:
{% extends "base.html" %} {% block content %} <h1>You are now viewing ...!</h1> <source src={{media_file}}> {% endblock %}
However all I see is <Response 200 OK> or something like that. No file to be seen!
Would I use a get_file() and then return Response(getfileVar) in that media_file argument?
Advertisement
Answer
send_file
returns a Response
object. It makes no sense to pass this to the template.
So you need two endpoints. One to display your website containing the media element and one to stream the file from the directory. I recommend using send_from_directory
for this.
This is a simple example that lists all files within a directory and offers them for playback or viewing. The distinction is made based on the mime type of the file. This is determined via guess_type
.
The exmpale uses the instance path to ensure separation of files and application.
import os from flask import ( Flask, render_template, send_from_directory ) from mimetypes import guess_type app = Flask(__name__) app.config['MEDIA_FOLDER'] = os.path.join(app.instance_path, 'media') try: os.makedirs(app.config['MEDIA_FOLDER']) except: pass def listfiles(target): for filename in os.listdir(target): mimetype = guess_type(os.path.join(target, filename)) yield ( filename, mimetype, ) @app.route('/') def index(): files = listfiles(app.config['MEDIA_FOLDER']) return render_template('index.html', **locals()) @app.route('/media/<path:filename>') def media(filename): return send_from_directory( app.config['MEDIA_FOLDER'], filename )
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> {% for filename, type in files -%} <div> {% set mimetype, encoding = type -%} {% if mimetype.startswith('audio') -%} <audio controls> <source src="{{ url_for('media', filename=filename) }}" type="{{ mimetype }}"> </audio> {% elif mimetype.startswith('image') -%} <img src="{{ url_for('media', filename=filename) }}" /> {% endif -%} </div> {% endfor -%} </body> </html>