Commit 052adfa4 authored by Duggan, John's avatar Duggan, John
Browse files

Support binary file uploads from local machine

parent 46d980b6
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ class FileUpload(vuetify.VBtn):
        extensions: Union[List[str], Tuple, None] = None,
        label: str = "",
        return_contents: Union[bool, Tuple] = True,
        use_bytes: Union[bool, Tuple] = False,
        **kwargs: Any,
    ) -> None:
        """Constructor for FileUpload.
@@ -40,6 +41,8 @@ class FileUpload(vuetify.VBtn):
        return_contents : Union[bool, Tuple], optional
            If true, the file contents will be stored in v_model. If false, a file path will be stored in v_model.
            Defaults to true.
        use_bytes : Union[bool, Tuple], optional
            If true, then files uploaded from the local machine will contain bytes rather than text.
        **kwargs
            All other arguments will be passed to the underlying
            `Button component <https://trame.readthedocs.io/en/latest/trame.widgets.vuetify3.html#trame.widgets.vuetify3.VBtn>`_.
@@ -54,6 +57,7 @@ class FileUpload(vuetify.VBtn):
        self._base_paths = base_paths if base_paths else ["/"]
        self._extensions = extensions if extensions else []
        self._return_contents = return_contents
        self._use_bytes = use_bytes
        self._ref_name = f"nova__fileupload_{self._next_id}"

        super().__init__(label, **kwargs)
@@ -83,6 +87,7 @@ class FileUpload(vuetify.VBtn):
            extensions=self._extensions,
            input_props={"classes": "d-none"},
            return_contents=self._return_contents,
            use_bytes=self._use_bytes,
        )

        with self:
+17 −5
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ from trame_server.core import State

from nova.mvvm._internal.utils import rgetdictvalue
from nova.mvvm.trame_binding import TrameBinding
from nova.trame._internal.utils import get_state_name, set_state_param
from nova.trame._internal.utils import get_state_name, get_state_param, set_state_param
from nova.trame.model.remote_file_input import RemoteFileInputModel
from nova.trame.view_model.remote_file_input import RemoteFileInputViewModel

@@ -35,6 +35,7 @@ class RemoteFileInput:
        extensions: Union[List[str], Tuple, None] = None,
        input_props: Optional[dict[str, Any]] = None,
        return_contents: Union[bool, Tuple] = False,
        use_bytes: Union[bool, Tuple] = False,
    ) -> None:
        """Constructor for RemoteFileInput.

@@ -58,6 +59,8 @@ class RemoteFileInput:
        return_contents : Union[bool, Tuple], optional
            If true, then the v_model will contain the contents of the file. If false, then the v_model will contain the
            path of the file. Defaults to false.
        use_bytes : Union[bool, Tuple], optional
            If true, then the file contents will be treated as bytestreams when calling decode_file.

        Returns
        -------
@@ -73,6 +76,7 @@ class RemoteFileInput:
        self.extensions = extensions if extensions else []
        self.input_props = dict(input_props) if input_props else {}
        self.return_contents = return_contents
        self.use_bytes = use_bytes

        if "__events" not in self.input_props:
            self.input_props["__events"] = []
@@ -286,9 +290,17 @@ class RemoteFileInput:
            self.decode_file(file.read())

    def decode_file(self, bytestream: bytes, set_contents: bool = False) -> None:
        use_bytes = get_state_param(self.state, self.use_bytes)

        decoded_content = bytestream.decode("latin1")
        if set_contents:
            self.set_v_model(decoded_content)
        else:
            if use_bytes:
                with NamedTemporaryFile(mode="wb", delete=False) as temp_file:
                    temp_file.write(bytestream)
                    temp_file.flush()
                    self.set_v_model(temp_file.name)
            else:
                with NamedTemporaryFile(mode="w", delete=False, encoding="utf-8") as temp_file:
                    temp_file.write(decoded_content)