Repository: gradio-app/gradio
Pull request: fix upload file delay
There was a delay between an uploaded file and then trigger for `change` and `upload` listeners. This was caused by the fact that files were actually getting uploaded *twice*, once in the svelte File component, and once in the client library when submitting data. This us because the client looks to see if there's any blob in the component data and uploads it. I removed the blob in the component so that the client does not resubmit - ideally we could let the client handle all uploading but the upload animation and dispatching of "change" and "submit" within the component won't work with that, so it's handled only in the component now. 

Fixes: #4385 

To test, run any demo that has a change or upload trigger on file, example below. Previously, you would see a lag between the finishing of the upload animation and triggering of the backend. You would also two network requests made "/upload" made sequentially. These should be fixed.

```python
import os
from zipfile import ZipFile
import gradio as gr


def zip_files(files):
    with ZipFile("tmp.zip", "w") as zipObj:
        for idx, file in enumerate(files):
            zipObj.write(file.name, file.name.split("/")[-1])
    return "tmp.zip"

with gr.Blocks() as demo:
    file = gr.File(label="a", file_count="multiple")
    zipped = gr.File(label="b")
    file.change(zip_files, file, zipped)

demo.queue().launch()
```

Problem statement:
Delay between file upload and change file handler with no animation
### Describe the bug

If there's a File component with a change listener, there's a period of time between upload and firing the change event with no pending animation. Can be very long when uploading large files, especially on Spaces. 

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Reproduction

```python
import os
from zipfile import ZipFile
import gradio as gr


def zip_files(files):
    with ZipFile("tmp.zip", "w") as zipObj:
        for idx, file in enumerate(files):
            zipObj.write(file.name, file.name.split("/")[-1])
    return "tmp.zip"

with gr.Blocks() as demo:
    file = gr.File(file_count="multiple")
    zipped = gr.File()
    file.change(zip_files, file, zipped)


if __name__ == "__main__":
    demo.launch()
```

### Screenshot

_No response_

### Logs

```shell
N/A
```


### System Info

```shell
gradio==3.32.0
mac os
```


### Severity

serious, but I can work around it

Hints from issue discussion:

Commit message: changes

Patch to review:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b91b22a0ae..f197b754da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@
 - Fixed Dropdown height rendering in Columns by [@aliabid94](https://github.com/aliabid94) in [PR 4584](https://github.com/gradio-app/gradio/pull/4584) 
 - Fixed bug where `AnnotatedImage` css styling was causing the annotation masks to not be displayed correctly by  [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4628](https://github.com/gradio-app/gradio/pull/4628)
 - Ensure that Gradio does not silently fail when running on a port that is occupied by [@abidlabs](https://github.com/abidlabs) in [PR 4624](https://github.com/gradio-app/gradio/pull/4624).
+- Fix double upload bug that caused lag in file uploads by [@aliabid94](https://github.com/aliabid94) in [PR 4661](https://github.com/gradio-app/gradio/pull/4661)
 
 ## Other Changes:
 
diff --git a/js/app/src/components/File/File.svelte b/js/app/src/components/File/File.svelte
index c75410487b..1434f358cd 100644
--- a/js/app/src/components/File/File.svelte
+++ b/js/app/src/components/File/File.svelte
@@ -71,6 +71,7 @@
 						(Array.isArray(_value) ? _value : [_value]).forEach(
 							async (file_data, i) => {
 								file_data.data = await blobToBase64(file_data.blob!);
+								file_data.blob = null;								
 							}
 						);
 					} else {
@@ -80,10 +81,11 @@
 									file_data.orig_name = file_data.name;
 									file_data.name = response.files[i];
 									file_data.is_file = true;
+									file_data.blob = null;
 								}
 							}
 						);
-						_value = normalise_file(value, root, root_url);
+						old_value = _value = normalise_file(value, root, root_url);
 					}
 					dispatch("change");
 					dispatch("upload");
diff --git a/js/app/src/components/UploadButton/UploadButton.svelte b/js/app/src/components/UploadButton/UploadButton.svelte
index 2071c4970b..9d1c3ae31a 100644
--- a/js/app/src/components/UploadButton/UploadButton.svelte
+++ b/js/app/src/components/UploadButton/UploadButton.svelte
@@ -32,6 +32,7 @@
 				(Array.isArray(detail) ? detail : [detail]).forEach(
 					async (file_data, i) => {
 						file_data.data = await blobToBase64(file_data.blob!);
+						file_data.blob = null;
 					}
 				);
 			} else {
@@ -40,6 +41,7 @@
 						file_data.orig_name = file_data.name;
 						file_data.name = response.files[i];
 						file_data.is_file = true;
+						file_data.blob = null;
 					}
 				});
 			}


Code review comments:
diff_hunk: @@ -80,10 +81,11 @@
 									file_data.orig_name = file_data.name;
 									file_data.name = response.files[i];
 									file_data.is_file = true;
+									file_data.blob = null;
path: js/app/src/components/File/File.svelte
text: @user1:
Think we just need to use `undefined` for all of these empty blob values and those errors.

@user1:
beat me to it.