Repository: Lightning-Universe/lightning-flash

Issue:
`download_data` from `flash.core.data.utils` connects to the internet before checking if a file exists
## 🐛 Bug

In many supercomputers, process of running ML codes is to first run the download part on the login nodes (which have access to the internet), and stop the code right before the actual training starts. 

Then, when you run on the compute nodes (the ones with the actual gpus and no internet access), you let the code run to the end. In other frameworks, data downloaders detect the files' presence and skip it before ever trying to connect to the internet.

Flash tries first to check file size in [this line](https://github.com/Lightning-Universe/lightning-flash/blob/18ff71e228ea0d68d6564ae454a7053e503dee15/src/flash/core/data/utils.py#L86), which will freeze in a machine without internet.

### To Reproduce

call "download_data" on a machine with no internet access

#### Code sample

```
from flash.core.data.utils import download_data
download_data("https://pl-flash-data.s3.amazonaws.com/hymenoptera_data.zip", "data/")
```

### Expected behavior

If the file is already there, skip download

### Environment

 - OS (e.g., Linux): Centos 8.6
 - Python version: 3.10
 - PyTorch/Lightning/Flash Version (e.g., 1.10/1.5/0.7): Pytorch 1.12.1, Lightning 0.8.4, Flash 0.8.1.post0
 - GPU models and configuration: 16x A100 40GB
 - Any other relevant information:

### Additional context

Fast.ai's fastdownload, for example, does not suffer from this - if the file is there, it doesn't try to download it, even if it's of the wrong size: [fastdownload link](https://github.com/fastai/fastcore/blob/1f6844d44d6e0e26b393cecd37818dbb4d391aca/fastcore/net.py#L180)


Discussion:
Nice catch. :detective: Would you be interested in sending a fix? :rabbit: 

Resolving patch:
diff --git a/src/flash/core/data/utils.py b/src/flash/core/data/utils.py
--- a/src/flash/core/data/utils.py
+++ b/src/flash/core/data/utils.py
@@ -59,7 +59,7 @@
 }
 
 
-def download_data(url: str, path: str = "data/", verbose: bool = False) -> None:
+def download_data(url: str, path: str = "data/", verbose: bool = False, chunk_size: int = 1024) -> None:
     """Download file with progressbar.
 
     # Code adapted from: https://gist.github.com/ruxi/5d6803c116ec1130d484a4ab8c00c603
@@ -78,39 +78,42 @@ def download_data(url: str, path: str = "data/", verbose: bool = False) -> None:
         [...]
 
     """
+    local_filename = os.path.join(path, url.split("/")[-1])
+    if os.path.exists(local_filename):
+        if verbose:
+            print(f"local file already exists: '{local_filename}'")
+        return
+
+    os.makedirs(path, exist_ok=True)
     # Disable warning about making an insecure request
     urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
 
-    if not os.path.exists(path):
-        os.makedirs(path)
-    local_filename = os.path.join(path, url.split("/")[-1])
     r = requests.get(url, stream=True, verify=False)
     file_size = int(r.headers["Content-Length"]) if "Content-Length" in r.headers else 0
-    chunk_size = 1024
     num_bars = int(file_size / chunk_size)
     if verbose:
-        print({"file_size": file_size})
-        print({"num_bars": num_bars})
-
-    if not os.path.exists(local_filename):
-        with open(local_filename, "wb") as fp:
-            for chunk in tq(
-                r.iter_content(chunk_size=chunk_size),
-                total=num_bars,
-                unit="KB",
-                desc=local_filename,
-                leave=True,  # progressbar stays
-            ):
-                fp.write(chunk)  # type: ignore
-
-    def extract_tarfile(file_path: str, extract_path: str, mode: str):
-        if os.path.exists(file_path):
-            with tarfile.open(file_path, mode=mode) as tar_ref:
-                for member in tar_ref.getmembers():
-                    try:
-                        tar_ref.extract(member, path=extract_path, set_attrs=False)
-                    except PermissionError:
-                        raise PermissionError(f"Could not extract tar file {file_path}")
+        print(f"file size: {file_size}")
+        print(f"num bars: {num_bars}")
+
+    with open(local_filename, "wb") as fp:
+        for chunk in tq(
+            r.iter_content(chunk_size=chunk_size),
+            total=num_bars,
+            unit="KB",
+            desc=local_filename,
+            leave=True,  # progressbar stays
+        ):
+            fp.write(chunk)  # type: ignore
+
+    def extract_tarfile(file_path: str, extract_path: str, mode: str) -> None:
+        if not os.path.exists(file_path):
+            return
+        with tarfile.open(file_path, mode=mode) as tar_ref:
+            for member in tar_ref.getmembers():
+                try:
+                    tar_ref.extract(member, path=extract_path, set_attrs=False)
+                except PermissionError:
+                    raise PermissionError(f"Could not extract tar file {file_path}")
 
     if ".zip" in local_filename:
         if os.path.exists(local_filename):


Test patch: