diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b218b454c..e61f40722a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -70,6 +70,7 @@ By [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3165](https://github.
 * Fixes `gr.utils.delete_none` to only remove props whose values are `None` from the config by [@abidlabs](https://github.com/abidlabs) in [PR 3188](https://github.com/gradio-app/gradio/pull/3188) 
 * Fix bug where embedded demos were not loading files properly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3177](https://github.com/gradio-app/gradio/pull/3177)
 * The `change` event is now triggered when users click the 'Clear All' button of the multiselect DropDown component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3195](https://github.com/gradio-app/gradio/pull/3195)
+* Stops File component from freezing when a large file is uploaded by [@aliabid94](https://github.com/aliabid94) in [PR 3191](https://github.com/gradio-app/gradio/pull/3191)
 * Support Chinese pinyin in Dataframe by [@aliabid94](https://github.com/aliabid94) in [PR 3206](https://github.com/gradio-app/gradio/pull/3206)
 * The `clear` event is now triggered when images are cleared by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3218](https://github.com/gradio-app/gradio/pull/3218)
 * Fix bug where auth cookies where not sent when connecting to an app via http by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3223](https://github.com/gradio-app/gradio/pull/3223)
diff --git a/demo/zip_files/.gitignore b/demo/zip_files/.gitignore
new file mode 100644
index 0000000000..8e9b8f2027
--- /dev/null
+++ b/demo/zip_files/.gitignore
@@ -0,0 +1 @@
+tmp.zip
\ No newline at end of file
diff --git a/demo/zip_files/run.ipynb b/demo/zip_files/run.ipynb
index f8f70a15cb..21810513c7 100644
--- a/demo/zip_files/run.ipynb
+++ b/demo/zip_files/run.ipynb
@@ -1 +1 @@
-{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: zip_files"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/titanic.csv https://github.com/gradio-app/gradio/raw/main/demo/zip_files/files/titanic.csv\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/zip_files/tmp.zip"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import os\n", "from zipfile import ZipFile\n", "\n", "import gradio as gr\n", "\n", "\n", "def zip_files(files):\n", "    with ZipFile(\"tmp.zip\", \"w\") as zipObj:\n", "        for idx, file in enumerate(files):\n", "            zipObj.write(file.name, \"file\" + str(idx))\n", "    return \"tmp.zip\"\n", "\n", "demo = gr.Interface(\n", "    zip_files,\n", "    gr.File(file_count=\"multiple\", file_types=[\"text\", \".json\", \".csv\"]),\n", "    \"file\",\n", "    examples=[[[os.path.join(os.path.abspath(''),\"files/titanic.csv\"), \n", "    os.path.join(os.path.abspath(''),\"files/titanic.csv\"), \n", "    os.path.join(os.path.abspath(''),\"files/titanic.csv\")]]], \n", "    cache_examples=True\n", ")\n", "\n", "if __name__ == \"__main__\":\n", "    demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
+{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: zip_files"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/titanic.csv https://github.com/gradio-app/gradio/raw/main/demo/zip_files/files/titanic.csv"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import os\n", "from zipfile import ZipFile\n", "\n", "import gradio as gr\n", "\n", "\n", "def zip_files(files):\n", "    with ZipFile(\"tmp.zip\", \"w\") as zipObj:\n", "        for idx, file in enumerate(files):\n", "            zipObj.write(file.name, file.name.split(\"/\")[-1])\n", "    return \"tmp.zip\"\n", "\n", "demo = gr.Interface(\n", "    zip_files,\n", "    gr.File(file_count=\"multiple\", file_types=[\"text\", \".json\", \".csv\"]),\n", "    \"file\",\n", "    examples=[[[os.path.join(os.path.abspath(''),\"files/titanic.csv\"), \n", "    os.path.join(os.path.abspath(''),\"files/titanic.csv\"), \n", "    os.path.join(os.path.abspath(''),\"files/titanic.csv\")]]], \n", "    cache_examples=True\n", ")\n", "\n", "if __name__ == \"__main__\":\n", "    demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/zip_files/run.py b/demo/zip_files/run.py
index 191bf4aab4..1ae6436c67 100644
--- a/demo/zip_files/run.py
+++ b/demo/zip_files/run.py
@@ -7,7 +7,7 @@ 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" + str(idx))
+            zipObj.write(file.name, file.name.split("/")[-1])
     return "tmp.zip"
 
 demo = gr.Interface(
diff --git a/demo/zip_files/tmp.zip b/demo/zip_files/tmp.zip
deleted file mode 100644
index c98df4f931..0000000000
Binary files a/demo/zip_files/tmp.zip and /dev/null differ
diff --git a/gradio/processing_utils.py b/gradio/processing_utils.py
index e228d96b2f..7837d9628c 100644
--- a/gradio/processing_utils.py
+++ b/gradio/processing_utils.py
@@ -15,8 +15,10 @@ from io import BytesIO
 from pathlib import Path
 from typing import Dict, Set, Tuple
 
+import aiofiles
 import numpy as np
 import requests
+from fastapi import UploadFile
 from ffmpy import FFmpeg, FFprobe, FFRuntimeError
 from PIL import Image, ImageOps, PngImagePlugin
 
@@ -403,6 +405,19 @@ class TempFileManager:
         self.temp_files.add(full_temp_file_path)
         return full_temp_file_path
 
+    async def save_uploaded_file(self, file: UploadFile, upload_dir: str) -> str:
+        prefix, extension = self.get_prefix_and_extension(file.filename)
+        output_file_obj = tempfile.NamedTemporaryFile(
+            delete=False, dir=upload_dir, suffix=f"{extension}", prefix=f"{prefix}_"
+        )
+        async with aiofiles.open(output_file_obj.name, "wb") as output_file:
+            while True:
+                content = await file.read(100 * 1024 * 1024)
+                if not content:
+                    break
+                await output_file.write(content)
+        return str(utils.abspath(output_file_obj.name))
+
     def download_temp_copy_if_needed(self, url: str) -> str:
         """Downloads a file and makes a temporary file path for a copy if does not already
         exist. Otherwise returns the path to the existing temp file."""
diff --git a/gradio/routes.py b/gradio/routes.py
index 5d3fe1ad85..ccb1453d0c 100644
--- a/gradio/routes.py
+++ b/gradio/routes.py
@@ -10,6 +10,7 @@ import mimetypes
 import os
 import posixpath
 import secrets
+import tempfile
 import traceback
 from collections import defaultdict
 from copy import deepcopy
@@ -21,7 +22,7 @@ import httpx
 import markupsafe
 import orjson
 import pkg_resources
-from fastapi import Depends, FastAPI, HTTPException, WebSocket, status
+from fastapi import Depends, FastAPI, File, HTTPException, UploadFile, WebSocket, status
 from fastapi.middleware.cors import CORSMiddleware
 from fastapi.responses import (
     FileResponse,
@@ -43,6 +44,7 @@ from gradio.context import Context
 from gradio.data_classes import PredictBody, ResetBody
 from gradio.documentation import document, set_documentation_group
 from gradio.exceptions import Error
+from gradio.processing_utils import TempFileManager
 from gradio.queueing import Estimation, Event
 from gradio.utils import cancel_tasks, run_coro_in_background, set_task_name
 
@@ -109,6 +111,7 @@ class App(FastAPI):
         self.lock = asyncio.Lock()
         self.queue_token = secrets.token_urlsafe(32)
         self.startup_events_triggered = False
+        self.uploaded_file_dir = str(utils.abspath(tempfile.mkdtemp()))
         super().__init__(**kwargs)
 
     def configure_app(self, blocks: gradio.Blocks) -> None:
@@ -297,17 +300,19 @@ class App(FastAPI):
                 )
             abs_path = str(utils.abspath(path_or_url))
             in_app_dir = utils.abspath(app.cwd) in utils.abspath(path_or_url).parents
-            created_by_app = str(utils.abspath(path_or_url)) in set().union(
-                *blocks.temp_file_sets
-            )
+            created_by_app = abs_path in set().union(*blocks.temp_file_sets)
             in_file_dir = any(
                 (
                     utils.abspath(dir) in utils.abspath(path_or_url).parents
                     for dir in blocks.file_directories
                 )
             )
+            was_uploaded = (
+                utils.abspath(app.uploaded_file_dir)
+                in utils.abspath(path_or_url).parents
+            )
 
-            if in_app_dir or created_by_app or in_file_dir:
+            if in_app_dir or created_by_app or in_file_dir or was_uploaded:
                 range_val = request.headers.get("Range", "").strip()
                 if range_val.startswith("bytes=") and "-" in range_val:
                     range_val = range_val[6:]
@@ -514,6 +519,20 @@ class App(FastAPI):
         async def get_queue_status():
             return app.get_blocks()._queue.get_estimation()
 
+        @app.post("/upload", dependencies=[Depends(login_check)])
+        async def upload_file(
+            files: List[UploadFile] = File(...),
+        ):
+            output_files = []
+            file_manager = TempFileManager()
+            for input_file in files:
+                output_files.append(
+                    await file_manager.save_uploaded_file(
+                        input_file, app.uploaded_file_dir
+                    )
+                )
+            return output_files
+
         @app.on_event("startup")
         @app.get("/startup-events")
         async def startup_events():
diff --git a/test/test_files/alphabet.txt b/test/test_files/alphabet.txt
new file mode 100644
index 0000000000..e85d5b4528
--- /dev/null
+++ b/test/test_files/alphabet.txt
@@ -0,0 +1 @@
+abcdefghijklmnopqrstuvwxyz
\ No newline at end of file
diff --git a/test/test_routes.py b/test/test_routes.py
index 8934113f6e..23858cf07f 100644
--- a/test/test_routes.py
+++ b/test/test_routes.py
@@ -54,6 +54,17 @@ class TestRoutes:
         response = test_client.get("/config/")
         assert response.status_code == 200
 
+    def test_upload_route(self, test_client):
+        response = test_client.post(
+            "/upload", files={"files": open("test/test_files/alphabet.txt", "r")}
+        )
+        assert response.status_code == 200
+        file = response.json()[0]
+        assert "alphabet" in file
+        assert file.endswith(".txt")
+        with open(file) as saved_file:
+            assert saved_file.read() == "abcdefghijklmnopqrstuvwxyz"
+
     def test_predict_route(self, test_client):
         response = test_client.post(
             "/api/predict/", json={"data": ["test"], "fn_index": 0}
diff --git a/ui/packages/app/src/api.ts b/ui/packages/app/src/api.ts
index ce7605d900..1d27a28745 100644
--- a/ui/packages/app/src/api.ts
+++ b/ui/packages/app/src/api.ts
@@ -36,6 +36,10 @@ interface PostResponse {
 	error?: string;
 	[x: string]: any;
 }
+export interface UploadResponse {
+	error?: string;
+	files?: Array<string>;
+}
 const QUEUE_FULL_MSG = "This application is too busy. Keep trying!";
 const BROKEN_CONNECTION_MSG = "Connection errored out.";
 
@@ -55,6 +59,27 @@ export async function post_data(
 	const output: PostResponse = await response.json();
 	return [output, response.status];
 }
+
+export async function upload_files(
+	root: string,
+	files: Array<File>
+): Promise<UploadResponse> {
+	const formData = new FormData();
+	files.forEach((file) => {
+		formData.append("files", file);
+	});
+	try {
+		var response = await fetch(`${root}upload`, {
+			method: "POST",
+			body: formData
+		});
+	} catch (e) {
+		return { error: BROKEN_CONNECTION_MSG };
+	}
+	const output: UploadResponse["files"] = await response.json();
+	return { files: output };
+}
+
 interface UpdateOutput {
 	__type__: string;
 	[key: string]: unknown;
diff --git a/ui/packages/app/src/components/Dataset/ExampleComponents/File.svelte b/ui/packages/app/src/components/Dataset/ExampleComponents/File.svelte
index 4ea8f985cc..79d869a605 100644
--- a/ui/packages/app/src/components/Dataset/ExampleComponents/File.svelte
+++ b/ui/packages/app/src/components/Dataset/ExampleComponents/File.svelte
@@ -1,5 +1,5 @@
 <script lang="ts">
-	import type { FileData } from "../../File/types";
+	import type { FileData } from "@gradio/upload";
 
 	export let value: FileData;
 	export let type: "gallery" | "table";
diff --git a/ui/packages/app/src/components/File/File.svelte b/ui/packages/app/src/components/File/File.svelte
index 897d06a9b3..cac8ad40cd 100644
--- a/ui/packages/app/src/components/File/File.svelte
+++ b/ui/packages/app/src/components/File/File.svelte
@@ -1,10 +1,11 @@
 <script lang="ts">
 	import { createEventDispatcher } from "svelte";
-	import { File, FileUpload } from "@gradio/file";
-	import type { FileData } from "@gradio/upload";
+	import { File as FileComponent, FileUpload } from "@gradio/file";
+	import { blobToBase64, FileData } from "@gradio/upload";
 	import { normalise_file } from "@gradio/upload";
 	import { Block } from "@gradio/atoms";
 	import UploadText from "../UploadText.svelte";
+	import { upload_files } from "../../api";
 
 	import StatusTracker from "../StatusTracker/StatusTracker.svelte";
 	import type { LoadingStatus } from "../StatusTracker/types";
@@ -26,20 +27,56 @@
 
 	export let loading_status: LoadingStatus;
 
-	let _value: null | FileData | Array<FileData>;
 	$: _value = normalise_file(value, root, root_url);
 
 	let dragging = false;
+	let pending_upload = false;
 
 	const dispatch = createEventDispatcher<{
 		change: undefined;
+		error: string;
 	}>();
 
 	$: {
-		if (value !== old_value) {
-			old_value = value;
+		if (_value !== old_value) {
+			old_value = _value;
+			if (_value === null) {
+				dispatch("change");
+				pending_upload = false;
+			} else if (mode === "dynamic") {
+				let files = (Array.isArray(_value) ? _value : [_value]).map(
+					(file_data) => file_data.blob!
+				);
+				let upload_value = _value;
+				pending_upload = true;
+				upload_files(root, files).then((response) => {
+					if (upload_value !== _value) {
+						// value has changed since upload started
+						return;
+					}
 
-			dispatch("change");
+					pending_upload = false;
+					if (response.error) {
+						(Array.isArray(_value) ? _value : [_value]).forEach(
+							async (file_data, i) => {
+								file_data.data = await blobToBase64(file_data.blob!);
+							}
+						);
+					} else {
+						(Array.isArray(_value) ? _value : [_value]).forEach(
+							(file_data, i) => {
+								if (response.files) {
+									file_data.orig_name = file_data.name;
+									file_data.name = response.files[i];
+									file_data.is_file = true;
+								}
+							}
+						);
+						_value = normalise_file(value, root, root_url);
+					}
+					dispatch("change");
+				});
+			}
 		}
 	}
 </script>
@@ -51,7 +88,12 @@
 	padding={false}
 	{elem_id}
 >
-	<StatusTracker {...loading_status} />
+	<StatusTracker
+		{...loading_status}
+		status={pending_upload
+			? "generating"
+			: loading_status?.status || "complete"}
+	/>
 
 	{#if mode === "dynamic"}
 		<FileUpload
@@ -68,6 +110,6 @@
 			<UploadText type="file" />
 		</FileUpload>
 	{:else}
-		<File value={_value} {label} {show_label} />
+		<FileComponent value={_value} {label} {show_label} />
 	{/if}
 </Block>
diff --git a/ui/packages/app/src/components/File/types.ts b/ui/packages/app/src/components/File/types.ts
deleted file mode 100644
index 97f5abcdc2..0000000000
--- a/ui/packages/app/src/components/File/types.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface FileData {
-	name: string;
-	size: number;
-	data: string;
-	is_example: false;
-}
diff --git a/ui/packages/app/src/components/UploadButton/UploadButton.svelte b/ui/packages/app/src/components/UploadButton/UploadButton.svelte
index bd6e391070..5b60a04b64 100644
--- a/ui/packages/app/src/components/UploadButton/UploadButton.svelte
+++ b/ui/packages/app/src/components/UploadButton/UploadButton.svelte
@@ -3,21 +3,34 @@
 	import type { Styles } from "@gradio/utils";
 	import type { FileData } from "@gradio/upload";
 	import { UploadButton } from "@gradio/upload-button";
+	import { upload_files } from "../../api";
+	import { blobToBase64 } from "@gradio/upload";
 	import { _ } from "svelte-i18n";
 
 	export let style: Styles = {};
 	export let elem_id: string = "";
 	export let visible: boolean = true;
 	export let label: string;
-	export let value: null | FileData | Array<FileData>;
+	export let value: null | FileData;
 	export let file_count: string;
 	export let file_types: Array<string> = ["file"];
+	export let root: string;
 
 	async function handle_upload({ detail }: CustomEvent<FileData>) {
 		value = detail;
+		console.log(detail);
 		await tick();
-		dispatch("change", value);
-		dispatch("upload", detail);
+		upload_files(root, [detail.blob!]).then(async (response) => {
+			if (response.error) {
+				detail.data = await blobToBase64(detail.blob!);
+			} else {
+				detail.orig_name = detail.name;
+				detail.name = response.files![0];
+				detail.is_file = true;
+			}
+			dispatch("change", value);
+			dispatch("upload", detail);
+		});
 	}
 
 	const dispatch = createEventDispatcher<{
diff --git a/ui/packages/file/src/File.svelte b/ui/packages/file/src/File.svelte
index fc8440a17f..4befa7a401 100644
--- a/ui/packages/file/src/File.svelte
+++ b/ui/packages/file/src/File.svelte
@@ -21,6 +21,6 @@
 
 <style>
 	.file-preview {
-		overflow-x: scroll;
+		overflow-x: auto;
 	}
 </style>
diff --git a/ui/packages/file/src/FilePreview.svelte b/ui/packages/file/src/FilePreview.svelte
index 6c0e6edeb8..c3d9a13fd9 100644
--- a/ui/packages/file/src/FilePreview.svelte
+++ b/ui/packages/file/src/FilePreview.svelte
@@ -2,11 +2,7 @@
 	import type { FileData } from "@gradio/upload";
 	import { Download } from "@gradio/icons";
 	import { IconButton } from "@gradio/atoms";
-	import {
-		display_file_name,
-		download_files,
-		display_file_size
-	} from "./utils";
+	import { display_file_name, display_file_size } from "./utils";
 
 	export let value: FileData | FileData[];
 </script>
@@ -24,13 +20,19 @@
 				</td>
 
 				<td class="download">
-					<a
-						href={download_files(file)}
-						target={window.__is_colab__ ? "_blank" : null}
-						download={window.__is_colab__ ? null : file.orig_name || file.name}
-					>
-						Download
-					</a>
+					{#if file.data}
+						<a
+							href={file.data}
+							target="_blank"
+							download={window.__is_colab__
+								? null
+								: file.orig_name || file.name}
+						>
+							Download
+						</a>
+					{:else}
+						Uploading...
+					{/if}
 				</td>
 			</tr>
 		{/each}
@@ -52,7 +54,7 @@
 		margin-bottom: var(--size-7);
 		width: var(--size-full);
 		max-height: var(--size-60);
-		overflow-y: scroll;
+		overflow-y: auto;
 		color: var(--color-text-body);
 	}
 	.file {
diff --git a/ui/packages/file/src/FileUpload.svelte b/ui/packages/file/src/FileUpload.svelte
index 0f195e6c05..2089245444 100644
--- a/ui/packages/file/src/FileUpload.svelte
+++ b/ui/packages/file/src/FileUpload.svelte
@@ -14,7 +14,9 @@
 	export let file_count: string = "single";
 	export let file_types: string[] | null = null;
 
-	async function handle_upload({ detail }: CustomEvent<FileData>) {
+	async function handle_upload({
+		detail
+	}: CustomEvent<FileData | Array<FileData>>) {
 		value = detail;
 		await tick();
 		dispatch("change", value);
@@ -28,10 +30,10 @@
 	}
 
 	const dispatch = createEventDispatcher<{
-		change: FileData | null;
+		change: Array<FileData> | FileData | null;
 		clear: undefined;
 		drag: boolean;
-		upload: FileData;
+		upload: Array<FileData> | FileData;
 		error: string;
 	}>();
 
@@ -55,16 +57,17 @@
 
 <BlockLabel {show_label} Icon={File} label={label || "File"} />
 
-{#if value === null}
+{#if value}
+	<ModifyUpload on:clear={handle_clear} absolute />
+	<FilePreview {value} />
+{:else}
 	<Upload
 		on:load={handle_upload}
 		filetype={accept_file_types}
+		parse_to_data_url={false}
 		{file_count}
 		bind:dragging
 	>
 		<slot />
 	</Upload>
-{:else}
-	<ModifyUpload on:clear={handle_clear} absolute />
-	<FilePreview {value} />
 {/if}
diff --git a/ui/packages/file/src/utils.ts b/ui/packages/file/src/utils.ts
index 30401457e3..5fc7753eee 100644
--- a/ui/packages/file/src/utils.ts
+++ b/ui/packages/file/src/utils.ts
@@ -19,10 +19,6 @@ export const display_file_name = (value: FileData): string => {
 	} else return str;
 };
 
-export const download_files = (value: FileData): string => {
-	return value.data;
-};
-
 export const display_file_size = (
 	value: FileData | Array<FileData>
 ): string => {
diff --git a/ui/packages/model3D/src/Model3D.svelte b/ui/packages/model3D/src/Model3D.svelte
index 430c04be31..bac77b6b17 100644
--- a/ui/packages/model3D/src/Model3D.svelte
+++ b/ui/packages/model3D/src/Model3D.svelte
@@ -2,7 +2,6 @@
 	import type { FileData } from "@gradio/upload";
 	import { BlockLabel, IconButton } from "@gradio/atoms";
 	import { File, Download } from "@gradio/icons";
-	import { download_files } from "./utils";
 
 	export let value: FileData | null;
 	export let clearColor: Array<number> = [0, 0, 0, 0];
@@ -81,7 +80,7 @@
 	<div class="model3D">
 		<div class="download">
 			<a
-				href={download_files(value)}
+				href={value.data}
 				target={window.__is_colab__ ? "_blank" : null}
 				download={window.__is_colab__ ? null : value.orig_name || value.name}
 			>
diff --git a/ui/packages/model3D/src/utils.ts b/ui/packages/model3D/src/utils.ts
index 30401457e3..5fc7753eee 100644
--- a/ui/packages/model3D/src/utils.ts
+++ b/ui/packages/model3D/src/utils.ts
@@ -19,10 +19,6 @@ export const display_file_name = (value: FileData): string => {
 	} else return str;
 };
 
-export const download_files = (value: FileData): string => {
-	return value.data;
-};
-
 export const display_file_size = (
 	value: FileData | Array<FileData>
 ): string => {
diff --git a/ui/packages/upload-button/package.json b/ui/packages/upload-button/package.json
index 75f8271093..57d56835af 100644
--- a/ui/packages/upload-button/package.json
+++ b/ui/packages/upload-button/package.json
@@ -9,6 +9,7 @@
 	"private": true,
 	"dependencies": {
 		"@gradio/button": "workspace:^0.0.1",
-		"@gradio/utils": "workspace:^0.0.1"
+		"@gradio/utils": "workspace:^0.0.1",
+		"@gradio/upload": "workspace:^0.0.1"
 	}
 }
diff --git a/ui/packages/upload-button/src/UploadButton.svelte b/ui/packages/upload-button/src/UploadButton.svelte
index 664dde7346..f1c060a8d2 100644
--- a/ui/packages/upload-button/src/UploadButton.svelte
+++ b/ui/packages/upload-button/src/UploadButton.svelte
@@ -2,7 +2,7 @@
 	import { Button } from "@gradio/button";
 	import type { Styles } from "@gradio/utils";
 	import { createEventDispatcher } from "svelte";
-	import type { FileData } from "./types";
+	import type { FileData } from "@gradio/upload";
 	import { type } from "@testing-library/user-event/dist/type";
 
 	export let style: Styles = {};
@@ -35,33 +35,30 @@
 
 	const loadFiles = (files: FileList) => {
 		let _files: Array<File> = Array.from(files);
-		if (!files.length || !window.FileReader) {
+		if (!files.length) {
 			return;
 		}
 		if (file_count === "single") {
 			_files = [files[0]];
 		}
-		var all_file_data: Array<FileData | string> = [];
+		var all_file_data: Array<FileData | File> = [];
 		_files.forEach((f, i) => {
-			let ReaderObj = new FileReader();
-			ReaderObj.readAsDataURL(f);
-			ReaderObj.onloadend = function () {
-				all_file_data[i] = include_file_metadata
-					? {
-							name: f.name,
-							size: f.size,
-							data: this.result as string
-					  }
-					: (this.result as string);
-				if (
-					all_file_data.filter((x) => x !== undefined).length === files.length
-				) {
-					dispatch(
-						"load",
-						file_count == "single" ? all_file_data[0] : all_file_data
-					);
-				}
-			};
+			all_file_data[i] = include_file_metadata
+				? {
+						name: f.name,
+						size: f.size,
+						data: "",
+						blob: f
+				  }
+				: f;
+			if (
+				all_file_data.filter((x) => x !== undefined).length === files.length
+			) {
+				dispatch(
+					"load",
+					file_count == "single" ? all_file_data[0] : all_file_data
+				);
+			}
 		});
 	};
 
diff --git a/ui/packages/upload-button/src/types.ts b/ui/packages/upload-button/src/types.ts
deleted file mode 100644
index d747ba8492..0000000000
--- a/ui/packages/upload-button/src/types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface FileData {
-	name: string;
-	orig_name?: string;
-	size?: number;
-	data: string;
-	is_file?: boolean;
-}
diff --git a/ui/packages/upload/src/Upload.svelte b/ui/packages/upload/src/Upload.svelte
index b2162734f5..1cfab91ae9 100644
--- a/ui/packages/upload/src/Upload.svelte
+++ b/ui/packages/upload/src/Upload.svelte
@@ -1,6 +1,7 @@
 <script lang="ts">
 	import { createEventDispatcher } from "svelte";
 	import type { FileData } from "./types";
+	import { blobToBase64 } from "./utils";
 
 	export let filetype: string | null = null;
 	export let include_file_metadata = true;
@@ -10,6 +11,7 @@
 	export let flex: boolean = true;
 	export let file_count: string = "single";
 	export let disable_click = false;
+	export let parse_to_data_url = true;
 
 	let hidden_upload: HTMLInputElement;
 
@@ -25,7 +27,7 @@
 		hidden_upload.click();
 	};
 
-	const loadFiles = (files: FileList) => {
+	const loadFiles = async (files: FileList) => {
 		let _files: Array<File> = Array.from(files);
 		if (!files.length || !window.FileReader) {
 			return;
@@ -33,41 +35,55 @@
 		if (file_count === "single") {
 			_files = [files[0]];
 		}
-		var all_file_data: Array<FileData | string> = [];
-		_files.forEach((f, i) => {
-			let ReaderObj = new FileReader();
-			ReaderObj.readAsDataURL(f);
-			ReaderObj.onloadend = function () {
-				all_file_data[i] = include_file_metadata
-					? {
-							name: f.name,
-							size: f.size,
-							data: this.result as string
-					  }
-					: (this.result as string);
-				if (
-					all_file_data.filter((x) => x !== undefined).length === files.length
-				) {
-					dispatch(
-						"load",
-						file_count == "single" ? all_file_data[0] : all_file_data
-					);
-				}
-			};
-		});
+
+		if (include_file_metadata) {
+			var file_metadata: Array<{ name: string; size: number }> = _files.map(
+				(f) => ({
+					name: f.name,
+					size: f.size
+				})
+			);
+		}
+		var load_file_data = [];
+		var file_data: Array<string> | Array<File> = [];
+		if (parse_to_data_url) {
+			file_data = await Promise.all(_files.map((f) => blobToBase64(f)));
+		} else {
+			file_data = _files;
+		}
+		if (include_file_metadata) {
+			if (parse_to_data_url) {
+				load_file_data = file_data.map((data, i) => ({
+					data,
+					...file_metadata[i]
+				}));
+			} else {
+				load_file_data = file_data.map((data, i) => ({
+					data: "",
+					blob: data,
+					...file_metadata[i]
+				}));
+			}
+		} else {
+			load_file_data = file_data;
+		}
+		dispatch(
+			"load",
+			file_count === "single" ? load_file_data[0] : load_file_data
+		);
 	};
 
-	const loadFilesFromUpload = (e: Event) => {
+	const loadFilesFromUpload = async (e: Event) => {
 		const target = e.target as HTMLInputElement;
 
 		if (!target.files) return;
-		loadFiles(target.files);
+		await loadFiles(target.files);
 	};
 
-	const loadFilesFromDrop = (e: DragEvent) => {
+	const loadFilesFromDrop = async (e: DragEvent) => {
 		dragging = false;
 		if (!e.dataTransfer?.files) return;
-		loadFiles(e.dataTransfer.files);
+		await loadFiles(e.dataTransfer.files);
 	};
 </script>
 
diff --git a/ui/packages/upload/src/types.ts b/ui/packages/upload/src/types.ts
index d747ba8492..6c61c6a631 100644
--- a/ui/packages/upload/src/types.ts
+++ b/ui/packages/upload/src/types.ts
@@ -3,5 +3,6 @@ export interface FileData {
 	orig_name?: string;
 	size?: number;
 	data: string;
+	blob?: File;
 	is_file?: boolean;
 }
diff --git a/ui/packages/upload/src/utils.ts b/ui/packages/upload/src/utils.ts
index 7ed63c225c..5147784b5d 100644
--- a/ui/packages/upload/src/utils.ts
+++ b/ui/packages/upload/src/utils.ts
@@ -35,3 +35,13 @@ export function normalise_file(
 	}
 	return file;
 }
+
+export const blobToBase64 = (blob: File): Promise<string> => {
+	const reader = new FileReader();
+	reader.readAsDataURL(blob);
+	return new Promise((resolve) => {
+		reader.onloadend = () => {
+			resolve(reader.result as string);
+		};
+	});
+};
diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml
index b45e4bbb8f..9abde11124 100644
--- a/ui/pnpm-lock.yaml
+++ b/ui/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: 5.4
+lockfileVersion: 5.3
 
 importers:
 
@@ -48,7 +48,7 @@ importers:
       '@tailwindcss/forms': 0.5.0_tailwindcss@3.1.6
       '@testing-library/dom': 8.11.3
       '@testing-library/svelte': 3.1.0_svelte@3.49.0
-      '@testing-library/user-event': 13.5.0_gzufz4q333be4gqfrvipwvqt6a
+      '@testing-library/user-event': 13.5.0_@testing-library+dom@8.11.3
       autoprefixer: 10.4.4_postcss@8.4.6
       babylonjs: 5.18.0
       babylonjs-loaders: 5.18.0
@@ -65,15 +65,15 @@ importers:
       postcss-nested: 5.0.6_postcss@8.4.6
       postcss-prefix-selector: 1.16.0_postcss@8.4.6
       prettier: 2.6.2
-      prettier-plugin-css-order: 1.3.0_ob5okuz2s5mlecytbeo2erc43a
-      prettier-plugin-svelte: 2.7.0_3cyj5wbackxvw67rnaarcmbw7y
+      prettier-plugin-css-order: 1.3.0_postcss@8.4.6+prettier@2.6.2
+      prettier-plugin-svelte: 2.7.0_prettier@2.6.2+svelte@3.49.0
       sirv: 2.0.2
       sirv-cli: 2.0.2
       svelte: 3.49.0
-      svelte-check: 2.8.0_mgmdnb6x5rpawk37gozc2sbtta
+      svelte-check: 2.8.0_postcss@8.4.6+svelte@3.49.0
       svelte-i18n: 3.3.13_svelte@3.49.0
-      svelte-preprocess: 4.10.6_mlkquajfpxs65rn6bdfntu7nmy
-      tailwindcss: 3.1.6_postcss@8.4.6
+      svelte-preprocess: 4.10.6_62d50a01257de5eec5be08cad9d3ed66
+      tailwindcss: 3.1.6
       tinyspy: 0.3.0
       typescript: 4.7.4
       vite: 2.9.9
@@ -373,9 +373,11 @@ importers:
   packages/upload-button:
     specifiers:
       '@gradio/button': workspace:^0.0.1
+      '@gradio/upload': workspace:^0.0.1
       '@gradio/utils': workspace:^0.0.1
     dependencies:
       '@gradio/button': link:../button
+      '@gradio/upload': link:../upload
       '@gradio/utils': link:../utils
 
   packages/utils:
@@ -725,7 +727,7 @@ packages:
       tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1'
     dependencies:
       mini-svg-data-uri: 1.4.4
-      tailwindcss: 3.1.6_postcss@8.4.6
+      tailwindcss: 3.1.6
     dev: false
 
   /@testing-library/dom/7.31.2:
@@ -766,7 +768,7 @@ packages:
       svelte: 3.49.0
     dev: false
 
-  /@testing-library/user-event/13.5.0_gzufz4q333be4gqfrvipwvqt6a:
+  /@testing-library/user-event/13.5.0_@testing-library+dom@8.11.3:
     resolution: {integrity: sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==}
     engines: {node: '>=10', npm: '>=6'}
     peerDependencies:
@@ -2981,19 +2983,6 @@ packages:
       postcss-value-parser: 4.2.0
       read-cache: 1.0.0
       resolve: 1.22.1
-    dev: true
-
-  /postcss-import/14.1.0_postcss@8.4.6:
-    resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==}
-    engines: {node: '>=10.0.0'}
-    peerDependencies:
-      postcss: ^8.0.0
-    dependencies:
-      postcss: 8.4.6
-      postcss-value-parser: 4.2.0
-      read-cache: 1.0.0
-      resolve: 1.22.1
-    dev: false
 
   /postcss-js/4.0.0_postcss@8.4.21:
     resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==}
@@ -3003,17 +2992,6 @@ packages:
     dependencies:
       camelcase-css: 2.0.1
       postcss: 8.4.21
-    dev: true
-
-  /postcss-js/4.0.0_postcss@8.4.6:
-    resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==}
-    engines: {node: ^12 || ^14 || >= 16}
-    peerDependencies:
-      postcss: ^8.3.3
-    dependencies:
-      camelcase-css: 2.0.1
-      postcss: 8.4.6
-    dev: false
 
   /postcss-less/6.0.0_postcss@8.4.6:
     resolution: {integrity: sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==}
@@ -3052,24 +3030,6 @@ packages:
       lilconfig: 2.0.6
       postcss: 8.4.21
       yaml: 1.10.2
-    dev: true
-
-  /postcss-load-config/3.1.4_postcss@8.4.6:
-    resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
-    engines: {node: '>= 10'}
-    peerDependencies:
-      postcss: '>=8.0.9'
-      ts-node: '>=9.0.0'
-    peerDependenciesMeta:
-      postcss:
-        optional: true
-      ts-node:
-        optional: true
-    dependencies:
-      lilconfig: 2.0.6
-      postcss: 8.4.6
-      yaml: 1.10.2
-    dev: false
 
   /postcss-nested/5.0.6_postcss@8.4.21:
     resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==}
@@ -3079,7 +3039,6 @@ packages:
     dependencies:
       postcss: 8.4.21
       postcss-selector-parser: 6.0.9
-    dev: true
 
   /postcss-nested/5.0.6_postcss@8.4.6:
     resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==}
@@ -3157,7 +3116,7 @@ packages:
       picocolors: 1.0.0
       source-map-js: 1.0.2
 
-  /prettier-plugin-css-order/1.3.0_ob5okuz2s5mlecytbeo2erc43a:
+  /prettier-plugin-css-order/1.3.0_postcss@8.4.6+prettier@2.6.2:
     resolution: {integrity: sha512-wOS4qlbUARCoiiuOG0TiB/j751soC3+gUnMMva5HVWKvHJdLNYqh+jXK3MvvixR6xkJVPxHSF7rIIhkHIuHTFg==}
     engines: {node: '>=14'}
     peerDependencies:
@@ -3172,7 +3131,7 @@ packages:
       - postcss
     dev: false
 
-  /prettier-plugin-svelte/2.7.0_3cyj5wbackxvw67rnaarcmbw7y:
+  /prettier-plugin-svelte/2.7.0_prettier@2.6.2+svelte@3.49.0:
     resolution: {integrity: sha512-fQhhZICprZot2IqEyoiUYLTRdumULGRvw0o4dzl5jt0jfzVWdGqeYW27QTWAeXhoupEZJULmNoH3ueJwUWFLIA==}
     peerDependencies:
       prettier: ^1.16.4 || ^2.0.0
@@ -3659,7 +3618,7 @@ packages:
       - sugarss
     dev: true
 
-  /svelte-check/2.8.0_mgmdnb6x5rpawk37gozc2sbtta:
+  /svelte-check/2.8.0_postcss@8.4.6+svelte@3.49.0:
     resolution: {integrity: sha512-HRL66BxffMAZusqe5I5k26mRWQ+BobGd9Rxm3onh7ZVu0nTk8YTKJ9vu3LVPjUGLU9IX7zS+jmwPVhJYdXJ8vg==}
     hasBin: true
     peerDependencies:
@@ -3672,7 +3631,7 @@ packages:
       picocolors: 1.0.0
       sade: 1.8.1
       svelte: 3.49.0
-      svelte-preprocess: 4.10.6_mlkquajfpxs65rn6bdfntu7nmy
+      svelte-preprocess: 4.10.6_62d50a01257de5eec5be08cad9d3ed66
       typescript: 4.7.4
     transitivePeerDependencies:
       - '@babel/core'
@@ -3763,7 +3722,7 @@ packages:
       typescript: 4.5.5
     dev: true
 
-  /svelte-preprocess/4.10.6_mlkquajfpxs65rn6bdfntu7nmy:
+  /svelte-preprocess/4.10.6_62d50a01257de5eec5be08cad9d3ed66:
     resolution: {integrity: sha512-I2SV1w/AveMvgIQlUF/ZOO3PYVnhxfcpNyGt8pxpUVhPfyfL/CZBkkw/KPfuFix5FJ9TnnNYMhACK3DtSaYVVQ==}
     engines: {node: '>= 9.11.2'}
     requiresBuild: true
@@ -3883,40 +3842,6 @@ packages:
       resolve: 1.22.1
     transitivePeerDependencies:
       - ts-node
-    dev: true
-
-  /tailwindcss/3.1.6_postcss@8.4.6:
-    resolution: {integrity: sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==}
-    engines: {node: '>=12.13.0'}
-    hasBin: true
-    peerDependencies:
-      postcss: ^8.0.9
-    dependencies:
-      arg: 5.0.2
-      chokidar: 3.5.3
-      color-name: 1.1.4
-      detective: 5.2.1
-      didyoumean: 1.2.2
-      dlv: 1.1.3
-      fast-glob: 3.2.11
-      glob-parent: 6.0.2
-      is-glob: 4.0.3
-      lilconfig: 2.0.6
-      normalize-path: 3.0.0
-      object-hash: 3.0.0
-      picocolors: 1.0.0
-      postcss: 8.4.6
-      postcss-import: 14.1.0_postcss@8.4.6
-      postcss-js: 4.0.0_postcss@8.4.6
-      postcss-load-config: 3.1.4_postcss@8.4.6
-      postcss-nested: 5.0.6_postcss@8.4.6
-      postcss-selector-parser: 6.0.10
-      postcss-value-parser: 4.2.0
-      quick-lru: 5.1.1
-      resolve: 1.22.1
-    transitivePeerDependencies:
-      - ts-node
-    dev: false
 
   /then-request/6.0.2:
     resolution: {integrity: sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==}