Repository: gradio-app/gradio

Issue:
Image example breaks/freezes tab
### Describe the bug

I select an example image in the space, it does not fully load and then my Spaces page freezes. The space works well when uploading my own image.

https://huggingface.co/spaces/keras-io/EDSR

Even if the error is in user side (I don't know), the space should likely not freeze like this.

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Reproduction

Go to https://huggingface.co/spaces/keras-io/EDSR and click example image

### Screenshot

<img width="1201" alt="Screen Shot 2022-06-10 at 4 35 05 PM" src="https://user-images.githubusercontent.com/7246357/173088896-e24cefb9-b853-418c-902a-4691b4fe62d7.png">


### Logs

```shell
Traceback (most recent call last):
  File "/home/user/.local/lib/python3.8/site-packages/gradio/routes.py", line 255, in run_predict
    output = await app.blocks.process_api(
  File "/home/user/.local/lib/python3.8/site-packages/gradio/blocks.py", line 538, in process_api
    predictions, duration = await self.call_function(fn_index, processed_input)
  File "/home/user/.local/lib/python3.8/site-packages/gradio/blocks.py", line 452, in call_function
    prediction = await anyio.to_thread.run_sync(
  File "/home/user/.local/lib/python3.8/site-packages/anyio/to_thread.py", line 31, in run_sync
    return await get_asynclib().run_sync_in_worker_thread(
  File "/home/user/.local/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 937, in run_sync_in_worker_thread
    return await future
  File "/home/user/.local/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 867, in run
    result = context.run(func, *args)
  File "/home/user/.local/lib/python3.8/site-packages/gradio/interface.py", line 495, in <lambda>
    lambda *args: self.run_prediction(args)[0]
  File "/home/user/.local/lib/python3.8/site-packages/gradio/interface.py", line 678, in run_prediction
    prediction = predict_fn(*processed_input)
  File "app.py", line 17, in infer
    inputs = load_images([image])
  File "/home/user/app/utils.py", line 21, in load_images
    x = np.clip(file.reshape(480, 640, 3) / 255, 0, 1)
AttributeError: 'NoneType' object has no attribute 'reshape'
```
```


### System Info

```shell
Spaces, Gradio 3.0.13
```


### Severity

serious, but I can work around it


Discussion:
Thanks @osanseviero, confirming that I see this issue. We'll look into this to see what's going on
I no longer get that same error as the code in the space (as well as the gradio version) have been updated since this was posted.

I'm pretty sure this is the same bug as #1867 as the output is a Gallery and cache_examples is set to true in spaces.

Will fix #1867 to see if this bug is fixed. 

Resolving patch:
diff --git a/gradio/components.py b/gradio/components.py
--- a/gradio/components.py
+++ b/gradio/components.py
@@ -13,6 +13,7 @@
 import pathlib
 import shutil
 import tempfile
+import uuid
 import warnings
 from copy import deepcopy
 from types import ModuleType
@@ -122,7 +123,7 @@ def save_file(self, file: tempfile._TemporaryFileWrapper, dir: str, label: str):
         """
         Saved flagged file and returns filepath
         """
-        label = "".join([char for char in label if char.isalnum() or char in "._- "])
+        label = processing_utils.strip_invalid_filename_characters(label)
         old_file_name = file.name
         output_dir = os.path.join(dir, label)
         if os.path.exists(output_dir):
@@ -3618,6 +3619,39 @@ def style(
 
         return IOComponent.style(self, rounded=rounded, container=container)
 
+    def save_flagged(
+        self, dir: str, label: Optional[str], data: List[str], encryption_key: bool
+    ) -> None | str:
+        if data is None:
+            return None
+
+        label = processing_utils.strip_invalid_filename_characters(label)
+        # join the label with the dir so that one directory stores all gallery
+        # outputs, e.g. <dir>/<component-label>
+        dir = os.path.join(dir, label)
+
+        # Save all the files belonging to this gallery in the gallery_path directory
+        gallery_path = str(uuid.uuid4())
+
+        for img_data in data:
+            self.save_flagged_file(dir, gallery_path, img_data, encryption_key)
+
+        # In the csv file, the row corresponding to this sample will list
+        # the path where all sub-images are stored, e.g. <component-label>/<uuid>
+        return os.path.join(label, gallery_path)
+
+    def restore_flagged(self, dir, data, encryption_key):
+        files = []
+        gallery_path = os.path.join(dir, data)
+        # Sort to preserve order
+        for file in sorted(os.listdir(gallery_path)):
+            file_path = os.path.join(gallery_path, file)
+            img = processing_utils.encode_file_to_base64(
+                file_path, encryption_key=encryption_key
+            )
+            files.append(img)
+        return files
+
 
 class Carousel(IOComponent, Changeable):
     """
diff --git a/gradio/processing_utils.py b/gradio/processing_utils.py
--- a/gradio/processing_utils.py
+++ b/gradio/processing_utils.py
@@ -514,3 +514,7 @@ def _scale(a, n, m, copy=True):
     image = _scale(image, 8 * itemsize_in, 8 * itemsize_out, copy=False)
     image += imin_out
     return image.astype(dtype_out)
+
+
+def strip_invalid_filename_characters(filename: str) -> str:
+    return "".join([char for char in filename if char.isalnum() or char in "._- "])


Test patch:
diff --git a/test/test_components.py b/test/test_components.py
--- a/test/test_components.py
+++ b/test/test_components.py
@@ -1,16 +1,17 @@
 import json
 import os
+import pathlib
 import tempfile
 import unittest
 from copy import deepcopy
 from difflib import SequenceMatcher
+from unittest.mock import patch
 
 import matplotlib.pyplot as plt
 import numpy as np
 import pandas as pd
 import PIL
 import pytest
-from requests import head
 
 import gradio as gr
 from gradio import media_data
@@ -1807,5 +1808,26 @@ def test_static(self):
         self.assertEqual(component.get_config().get("value"), "#000000")
 
 
+@patch("uuid.uuid4", return_value="my-uuid")
+def test_gallery_save_and_restore_flagged(my_uuid, tmp_path):
+    gallery = gr.Gallery()
+    test_file_dir = pathlib.Path(pathlib.Path(__file__).parent, "test_files")
+    data = [
+        gr.processing_utils.encode_file_to_base64(
+            pathlib.Path(test_file_dir, "bus.png")
+        ),
+        gr.processing_utils.encode_file_to_base64(
+            pathlib.Path(test_file_dir, "cheetah1.jpg")
+        ),
+    ]
+    label = "Gallery, 1"
+    path = gallery.save_flagged(str(tmp_path), label, data, encryption_key=None)
+    assert path == os.path.join("Gallery 1", "my-uuid")
+    assert sorted(os.listdir(os.path.join(tmp_path, path))) == ["0.png", "1.jpg"]
+
+    data_restored = gallery.restore_flagged(tmp_path, path, encryption_key=None)
+    assert data == data_restored
+
+
 if __name__ == "__main__":
     unittest.main()