fix download for in app browsing
This commit is contained in:
parent
97694cdd50
commit
384775dd36
62
app.py
62
app.py
@ -237,7 +237,7 @@ def api_browse(subpath):
|
||||
@app.route("/media/<path:subpath>")
|
||||
@auth.require_secret
|
||||
def serve_file(subpath):
|
||||
# ─── 1) Locate the real file on disk ───
|
||||
# 1) Locate the real file on disk
|
||||
root, *relative_parts = subpath.split('/')
|
||||
base_path = session['folders'].get(root)
|
||||
full_path = os.path.join(base_path or '', *relative_parts)
|
||||
@ -246,7 +246,7 @@ def serve_file(subpath):
|
||||
app.logger.error(f"File not found: {full_path}")
|
||||
return "File not found", 404
|
||||
|
||||
# ─── 2) Prep request info ───
|
||||
# 2) Prep request info
|
||||
mime, _ = mimetypes.guess_type(full_path)
|
||||
mime = mime or 'application/octet-stream'
|
||||
|
||||
@ -259,29 +259,18 @@ def serve_file(subpath):
|
||||
if mime == 'audio/mpeg' and request.method != 'HEAD':
|
||||
do_log = False
|
||||
|
||||
# ─── 3) Pick the right cache ───
|
||||
# 3) Pick cache
|
||||
if mime.startswith('audio/'): cache = cache_audio
|
||||
elif mime.startswith('image/'): cache = cache_image
|
||||
elif mime.startswith('video/'): cache = cache_video
|
||||
else: cache = cache_other
|
||||
|
||||
# ─── 4) Try to stream directly from diskcache ───
|
||||
# 4) Ensure cached on‑disk file and get its path
|
||||
try:
|
||||
# returns a file-like whose .name is the real path on disk
|
||||
with cache.read(subpath) as reader:
|
||||
file_path = reader.name
|
||||
filesize = os.path.getsize(file_path)
|
||||
response = send_file(
|
||||
file_path,
|
||||
mimetype= mime,
|
||||
conditional= True # enable Range / If-Modified / etc
|
||||
)
|
||||
cached_hit = True
|
||||
|
||||
except KeyError:
|
||||
# cache miss → generate & write back to cache
|
||||
cached_hit = False
|
||||
|
||||
# cache miss
|
||||
if mime.startswith('image/'):
|
||||
# ─── 4a) Image branch: thumbnail & cache the JPEG ───
|
||||
try:
|
||||
@ -289,51 +278,52 @@ def serve_file(subpath):
|
||||
img.thumbnail((1920, 1920))
|
||||
if img.mode in ("RGBA", "P"):
|
||||
img = img.convert("RGB")
|
||||
|
||||
thumb_io = io.BytesIO()
|
||||
img.save(thumb_io, format='JPEG', quality=85)
|
||||
thumb_io.seek(0)
|
||||
|
||||
# write thumbnail into diskcache as a real file
|
||||
cache.set(subpath, thumb_io, read=True)
|
||||
|
||||
# now re-open from cache to get the on-disk path
|
||||
with cache.read(subpath) as reader:
|
||||
file_path = reader.name
|
||||
filesize = os.path.getsize(file_path)
|
||||
response = send_file(
|
||||
file_path,
|
||||
mimetype= 'image/jpeg',
|
||||
conditional= True
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
app.logger.error(f"Image processing failed for {subpath}: {e}")
|
||||
abort(500)
|
||||
|
||||
else:
|
||||
# ─── 4b) Non-image branch: cache original file ───
|
||||
try:
|
||||
# store the real file on diskcache
|
||||
cache.set(subpath, open(full_path, 'rb'), read=True)
|
||||
|
||||
# read back to get its path
|
||||
with cache.read(subpath) as reader:
|
||||
file_path = reader.name
|
||||
filesize = os.path.getsize(file_path)
|
||||
response = send_file(
|
||||
file_path,
|
||||
mimetype= mime,
|
||||
conditional= True
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
app.logger.error(f"Failed to cache file {subpath}: {e}")
|
||||
abort(500)
|
||||
|
||||
# ─── 5) Common headers & logging ───
|
||||
filesize = os.path.getsize(file_path)
|
||||
cached_hit = True # or False if you want to pass that into your logger
|
||||
|
||||
# 5) Figure out download flag and filename
|
||||
ask_download = request.args.get('download') == 'true'
|
||||
filename = os.path.basename(full_path)
|
||||
|
||||
# 6) Single send_file call with proper attachment handling
|
||||
response = send_file(
|
||||
file_path,
|
||||
mimetype = mime,
|
||||
conditional = True,
|
||||
as_attachment = ask_download,
|
||||
download_name = filename if ask_download else None
|
||||
)
|
||||
|
||||
# Explicitly force inline if not downloading
|
||||
if not ask_download:
|
||||
response.headers['Content-Disposition'] = 'inline'
|
||||
|
||||
response.headers['Cache-Control'] = 'public, max-age=86400'
|
||||
|
||||
# 7) Logging
|
||||
if do_log:
|
||||
a.log_file_access(
|
||||
subpath, filesize, mime,
|
||||
|
||||
@ -101,37 +101,21 @@ audio.onended = function() {
|
||||
playerButton.innerHTML = playIcon;
|
||||
};
|
||||
|
||||
|
||||
|
||||
async function downloadAudio() {
|
||||
const audio = document.getElementById('globalAudio');
|
||||
const src = audio.currentSrc || audio.src;
|
||||
if (!src) return;
|
||||
|
||||
// Build a fresh URL every time
|
||||
const requestUrl = new URL(src, window.location.href);
|
||||
requestUrl.searchParams.set('_', Date.now());
|
||||
|
||||
// Force network fetch and include same‑origin credentials
|
||||
const response = await fetch(requestUrl.toString(), {
|
||||
credentials: 'same-origin',
|
||||
cache: 'no-store'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Download failed: ${response.status}`);
|
||||
}
|
||||
|
||||
// Turn the response into a blob, then download it
|
||||
const blob = await response.blob();
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
// Build the URL with your download flag + cache‑buster
|
||||
const downloadUrl = new URL(src, window.location.href);
|
||||
downloadUrl.searchParams.set('download', 'true');
|
||||
downloadUrl.searchParams.set('_', Date.now());
|
||||
|
||||
// Create a “real” link to that URL and click it
|
||||
const a = document.createElement('a');
|
||||
a.href = blobUrl;
|
||||
// Retain original filename if possible
|
||||
a.download = decodeURIComponent(src.split('/').pop() || 'audio');
|
||||
a.href = downloadUrl.toString();
|
||||
// NOTE: do NOT set a.download here – we want the server's Content-Disposition to drive it
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
|
||||
// Cleanup
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
const cacheName = 'gottesdienste-v1.7';
|
||||
const cacheName = 'gottesdienste-v1.8';
|
||||
const assets = [
|
||||
'/',
|
||||
'/static/app.css',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user