litestar-org / litestar

Production-ready, Light, Flexible and Extensible ASGI API framework | Effortlessly Build Performant APIs
https://litestar.dev/
MIT License
5.65k stars 384 forks source link

Enhancement: Allow customizing uploader. #1465

Closed 4n1qz5skwv closed 1 year ago

4n1qz5skwv commented 1 year ago

Discussed in https://github.com/orgs/litestar-org/discussions/1463

Originally posted by **4n1qz5skwv** April 9, 2023 Currently, Uploaded files are stored in temporary location. In order to save it elsewhere, we have to rewrite or copy it. Is it possible to setup a custom handler? Say, uploaded file will saved in my_dir/{uuid4}/filename.ext directly ?

Fund with Polar

Goldziher commented 1 year ago

Please specify exactly what you are requesting. Thanks

4n1qz5skwv commented 1 year ago

Please specify exactly what you are requesting. Thanks

If you are thinking of full blown customization may be this. https://docs.djangoproject.com/en/4.2/ref/files/uploads/#writing-custom-upload-handlers

But I'm thinking something simple, Just Give us an option to build the filepath.

async def foo(meta: dict) -> pathlib.Path:
    '''
    available file information in meta data, not sure what's available.
    will return a pathlib path
    litestar will use this path (by calling this function) to save the file.
    '''
    return pathlib.Path('/home/some_random_data/filename')

@get("/", uploader_file_path_builder=bar)
async def aaa() -> str:
    """<bar> similar to foo, we are setting this just for this route.
    otherwise, it would have used <foo> because <foo> is set during app init
    else it would have use <default SpooledTemporaryFile system>"""
    return "aaa"

app = Litestar(
    uploader_file_path_builder=foo,
)

(variable names, code structure, arguments are just for example)

Or, May be an option to Override Default File handler,

class MyFileHandler(DefaultFileHandler): # from litestar... import DefaultFileHandler

    def create_path(self):
        """here we will override the default path building system"""            
        return pathlib.Path('abc').absolute() # a file path

# Then Set/Use <MyFileHandler> class instead of <foo> <bar> functions.
app = Litestar(
    uploader_file_handler=MyFileHandler,
)

or list of handlers may be based on threshold value.

app = Litestar(
    uploader_file_handler=[
        {'threshold': 0, 'handler':MemoryFileHandler},
        {'threshold': 2048, 'handler':TemporaryFileHandler},
    ]
)