Working on streaming download files and or range selection for file downloads

This commit is contained in:
Scott Idem
2023-08-17 20:16:39 -04:00
parent 925760b13d
commit bea4975e7e
2 changed files with 117 additions and 6 deletions

View File

@@ -1,6 +1,6 @@
import datetime, os, pathlib, time
from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query, Response, status
from fastapi.responses import FileResponse
from fastapi.responses import FileResponse, StreamingResponse
from pydantic import BaseModel, EmailStr, Field
from typing import Dict, List, Optional, Set, Union
@@ -240,6 +240,7 @@ async def event_file_lookup(
async def download_event_file(
event_file_id: str = Query(..., min_length=11, max_length=22),
filename: str = Query(None, min_length=4, max_length=100),
streaming: bool = False,
commons: Common_Route_Params = Depends(common_route_params),
):
@@ -280,10 +281,17 @@ async def download_event_file(
if os.path.exists(file_path_w_subdir):
log.info('Hosted file found on server.')
return FileResponse(file_path_w_subdir, filename=filename)
if streaming:
log.warning('Streaming!!!')
def iterfile(): #
with open(file_path_w_subdir, mode="rb") as file_like: #
yield from file_like #
return StreamingResponse(iterfile(), media_type='video/mp4')
else:
return FileResponse(file_path_w_subdir, filename=filename)
else:
log.error(f'The hosted file was not found on the server. Hash: {hash_sha256}')
return mk_resp(data=False, status_code=404, response=commons.response, status_message=f'The hosted file was not found on the server. Hash: {hash_sha256}') # Not Found
return mk_resp(data=None, status_code=404, response=commons.response, status_message=f'The hosted file was not found on the server. Hash: {hash_sha256}') # Not Found
# ### END ### API Event File ### download_event_file() ###

View File

@@ -1,6 +1,9 @@
import datetime, hashlib, os, pathlib, shutil, time
from fastapi import APIRouter, Body, Depends, File, Form, Header, HTTPException, Query, Response, status, UploadFile
from fastapi.responses import FileResponse
# from fastapi.responses import FileResponse, StreamingResponse
from fastapi.responses import StreamingResponse
from baize.asgi.responses import FileResponse
# from baize.wsgi.responses import FileResponse
from pydantic import BaseModel, EmailStr, Field
from typing import Dict, List, Optional, Set, Union
from pdf2image import convert_from_path
@@ -157,6 +160,7 @@ async def directory_check(
async def download_hosted_file(
hosted_file_id: str = Query(..., min_length=11, max_length=22),
filename: str = Query(None, min_length=4, max_length=100),
streaming: bool = False,
commons: Common_Route_Params = Depends(common_route_params),
):
@@ -198,13 +202,112 @@ async def download_hosted_file(
log.info(f'Full file path with subdirectory: {file_path_w_subdir}')
if os.path.exists(file_path_w_subdir):
return FileResponse(file_path_w_subdir, filename=filename)
# log.info('Hosted file found on server.')
# return FileResponse(file_path_w_subdir, filename=filename)
log.info('Hosted file found on server.')
if streaming:
log.warning('Streaming!!!')
def iterfile(): #
with open(file_path_w_subdir, mode="rb") as file_like: #
yield from file_like #
return StreamingResponse(iterfile(), media_type='video/mp4')
else:
return FileResponse(file_path_w_subdir, filename=filename)
else:
log.error(f'The hosted file was not found on the server. Hash: {hash_sha256}')
return mk_resp(data=False, status_code=400, response=commons.response, status_message='The hosted file was not found on the server.') # Bad Request
return mk_resp(data=None, status_code=404, response=commons.response, status_message=f'The hosted file was not found on the server. Hash: {hash_sha256}') # Not Found
# ### END ### API Hosted File ### download_hosted_file() ###
# class ChunkFileResponse(Response):
# def __init__(self, *args, **kwargs) -> None:
# if len(args) == 1:
# kwargs = args[0]
# [kwargs.pop(k) for k in ['status_code', 'cookies', 'stat_result']]
# super().__init__(**kwargs)
# ### BEGIN ### API Hosted File ### stream_hosted_file() ###
# Updated 2023-08-17
# @router.get('/{hosted_file_id}/stream', response_model=Resp_Body_Base)
# @router.get('/{hosted_file_id}/stream', response_class=Resp_Body_Base)
# @router.get('/{hosted_file_id}/stream', response_class=FileResponse)
@router.get('/{hosted_file_id}/stream')
# def stream_hosted_file(
async def stream_hosted_file(
hosted_file_id: str = Query(..., min_length=11, max_length=22),
filename: str = Query(None, min_length=4, max_length=100),
streaming: bool = True,
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# ### SECTION ### Secondary data validation
if hosted_file_id := redis_lookup_id_random(record_id_random=hosted_file_id, table_name='hosted_file'): pass
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The hosted_file ID was invalid or not found.')
hosted_files_path = settings.FILES_PATH['hosted_files_root']
# hosted_files_path = '/home/scott/tmp/hosted_files_dev/'
log.info(f'Hosted Files Path: {hosted_files_path}')
if hosted_file_obj := load_hosted_file_obj(
hosted_file_id = hosted_file_id,
# inc_hosted_file = True,
inc_hosted_file_link_list = True,
):
pass
else:
return mk_resp(data=False, status_code=400, response=commons.response) # Bad Request
if not filename:
filename = hosted_file_obj.filename
log.info(f'Filename: {filename}')
dir_path = hosted_file_obj.directory_path
subdir_path = hosted_file_obj.subdirectory_path
hash_sha256 = hosted_file_obj.hash_sha256
hash_filename = hash_sha256+'.file'
if subdir_path:
full_subdirectory_path = os.path.join(hosted_files_path, subdir_path)
else:
full_subdirectory_path = hosted_files_path
log.debug(full_subdirectory_path)
pathlib.Path(full_subdirectory_path).mkdir(parents=True, exist_ok=True)
file_path_w_subdir = os.path.join(full_subdirectory_path, hash_filename)
log.info(f'Full file path with subdirectory: {file_path_w_subdir}')
if os.path.exists(file_path_w_subdir):
# log.info('Hosted file found on server.')
# return FileResponse(file_path_w_subdir, filename=filename)
log.info('Hosted file found on server.')
# return ChunkFileResponse(filepath=file_path_w_subdir)
# return FileResponse(file_path_w_subdir, filename=filename)
if streaming:
log.warning('Streaming!!!')
return FileResponse(filepath=file_path_w_subdir, content_type='video/mp4', download_name=filename)
# def iterfile(): #
# with open(file_path_w_subdir, mode="rb") as file_like: #
# yield from file_like #
# return FileResponse(iterfile(), download_name=filename)
# return StreamingResponse(iterfile(), media_type='video/mp4')
else:
return FileResponse(file_path_w_subdir, filename=filename)
else:
log.error(f'The hosted file was not found on the server. Hash: {hash_sha256}')
return mk_resp(data=None, status_code=404, response=commons.response, status_message=f'The hosted file was not found on the server. Hash: {hash_sha256}') # Not Found
# ### END ### API Hosted File ### stream_hosted_file() ###
# ### BEGIN ### API Hosted File Route ### upload_files() ###
# This just needs to return the correct model for a hosted_file
# Everything else seems to be working well