test_file_upload.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. # Copyright 2021-2025 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. import inspect
  12. import io
  13. import os
  14. import pathlib
  15. import tempfile
  16. import pytest
  17. from taipy.gui import Gui
  18. from taipy.gui.data.data_scope import _DataScopes
  19. from taipy.gui.utils import _get_non_existent_file_path
  20. def test_file_upload_no_varname(gui: Gui, helpers):
  21. gui.run(run_server=False)
  22. flask_client = gui._server.test_client()
  23. # Get the jsx once so that the page will be evaluated -> variable will be registered
  24. sid = helpers.create_scope_and_get_sid(gui)
  25. with pytest.warns(UserWarning):
  26. ret = flask_client.post(f"/taipy-uploads?client_id={sid}")
  27. assert ret.status_code == 400
  28. def test_file_upload_no_blob(gui: Gui, helpers):
  29. gui.run(run_server=False)
  30. flask_client = gui._server.test_client()
  31. # Get the jsx once so that the page will be evaluated -> variable will be registered
  32. sid = helpers.create_scope_and_get_sid(gui)
  33. with pytest.warns(UserWarning):
  34. ret = flask_client.post(f"/taipy-uploads?client_id={sid}", data={"var_name": "varname"})
  35. assert ret.status_code == 400
  36. def test_file_upload_no_filename(gui: Gui, helpers):
  37. gui.run(run_server=False)
  38. flask_client = gui._server.test_client()
  39. file = (io.BytesIO(b"abcdef"), "")
  40. # Get the jsx once so that the page will be evaluated -> variable will be registered
  41. sid = helpers.create_scope_and_get_sid(gui)
  42. with pytest.warns(UserWarning):
  43. ret = flask_client.post(f"/taipy-uploads?client_id={sid}", data={"var_name": "varname", "blob": file})
  44. assert ret.status_code == 400
  45. def test_file_upload_simple(gui: Gui, helpers):
  46. gui.run(run_server=False)
  47. flask_client = gui._server.test_client()
  48. # Get the jsx once so that the page will be evaluated -> variable will be registered
  49. sid = helpers.create_scope_and_get_sid(gui)
  50. file_name = "test.jpg"
  51. file = (io.BytesIO(b"abcdef"), file_name)
  52. upload_path = pathlib.Path(gui._get_config("upload_folder", tempfile.gettempdir()))
  53. file_name = _get_non_existent_file_path(upload_path, file_name).name
  54. ret = flask_client.post(
  55. f"/taipy-uploads?client_id={sid}",
  56. data={"var_name": "varname", "blob": file},
  57. content_type="multipart/form-data",
  58. )
  59. assert ret.status_code == 200
  60. created_file = upload_path / file_name
  61. assert created_file.exists()
  62. def test_file_upload_multi_part(gui: Gui, helpers):
  63. gui.run(run_server=False)
  64. flask_client = gui._server.test_client()
  65. # Get the jsx once so that the page will be evaluated -> variable will be registered
  66. sid = helpers.create_scope_and_get_sid(gui)
  67. file_name = "test2.jpg"
  68. file0 = (io.BytesIO(b"abcdef"), file_name)
  69. file1 = (io.BytesIO(b"abcdef"), file_name)
  70. upload_path = pathlib.Path(gui._get_config("upload_folder", tempfile.gettempdir()))
  71. file_name = _get_non_existent_file_path(upload_path, file_name).name
  72. ret = flask_client.post(
  73. f"/taipy-uploads?client_id={sid}",
  74. data={"var_name": "varname", "blob": file0, "total": "2", "part": "0"},
  75. content_type="multipart/form-data",
  76. )
  77. assert ret.status_code == 200
  78. ret = flask_client.post(
  79. f"/taipy-uploads?client_id={sid}",
  80. data={"var_name": "varname", "blob": file1, "total": "2", "part": "1"},
  81. content_type="multipart/form-data",
  82. )
  83. assert ret.status_code == 200
  84. file_path = upload_path / file_name
  85. assert file_path.exists()
  86. def test_file_upload_multiple(gui: Gui, helpers):
  87. var_name = "varname"
  88. gui._set_frame(inspect.currentframe())
  89. gui.run(run_server=False, single_client=True)
  90. flask_client = gui._server.test_client()
  91. with gui.get_server_instance().app_context():
  92. gui._bind_var_val(var_name, None)
  93. # Get the jsx once so that the page will be evaluated -> variable will be registered
  94. sid = _DataScopes._GLOBAL_ID
  95. file = (io.BytesIO(b"abcdef"), "test.jpg")
  96. ret = flask_client.post(
  97. f"/taipy-uploads?client_id={sid}", data={"var_name": var_name, "blob": file}, content_type="multipart/form-data"
  98. )
  99. assert ret.status_code == 200
  100. created_file = pathlib.Path(gui._get_config("upload_folder", tempfile.gettempdir())) / "test.jpg"
  101. assert created_file.exists()
  102. file2 = (io.BytesIO(b"abcdef"), "test2.jpg")
  103. ret = flask_client.post(
  104. f"/taipy-uploads?client_id={sid}",
  105. data={"var_name": var_name, "blob": file2, "multiple": "True"},
  106. content_type="multipart/form-data",
  107. )
  108. assert ret.status_code == 200
  109. created_file = pathlib.Path(gui._get_config("upload_folder", tempfile.gettempdir())) / "test2.jpg"
  110. assert created_file.exists()
  111. value = getattr(gui._bindings()._get_all_scopes()[sid], var_name)
  112. assert len(value) == 2
  113. def test_file_upload_folder(gui: Gui, helpers):
  114. gui._set_frame(inspect.currentframe())
  115. gui.run(run_server=False, single_client=True)
  116. flask_client = gui._server.test_client()
  117. sid = _DataScopes._GLOBAL_ID
  118. files = [(io.BytesIO(b"(^~^)"), "cutey.txt"), (io.BytesIO(b"(^~^)"), "cute_nested.txt")]
  119. folders = [["folder"], ["folder", "nested"]]
  120. for file, folder in zip(files, folders):
  121. path = os.path.join(*folder, file[1])
  122. response = flask_client.post(
  123. f"/taipy-uploads?client_id={sid}",
  124. data={"var_name": "cute_varname", "blob": file, "path": path},
  125. content_type="multipart/form-data",
  126. )
  127. assert response.status_code == 200
  128. assert os.path.isfile(os.path.join(gui._get_config("upload_folder", tempfile.gettempdir()), path))