How I Created a File Sharing Website using Simple REACT
Tags: react, javascript, webdev, beginners
Published: 2023-07-25 15:41:20

## Introduction

Welcome Dev Enthusiasts! In this blog, I will take you through the journey of developing [FreeShare](https://freeshare.vercel.app), a free online file sharing platform that allows users to share files easily with just a 5-digit code, without the need for sign-up, email, or phone number verification. We'll dive into the features, architecture, and the code behind FreeShare, explaining how it works and highlighting some of the main functionalities.To share my knowledge i have posted the code in my github [Check Out Here](https://github.com/Varshithvhegde/FreeShare/)

I had already created a file sharing application last year by just using html,css and javascript for that [check this blog](https://dev.to/varshithvhegde/how-i-created-a-file-sharing-website-using-simple-javascript-355g) and Website is Named [Anyshare](https://anyshare.vercel.app)

## Background - The Need for FreeShare
![Free Share](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gavt9liitpwkoe9lvcc7.png)

The idea of FreeShare originated from the success of the previous project, AnyShare. While AnyShare was a well-received platform for file sharing, it had some loopholes and limitations that needed to be addressed. With FreeShare, the aim was to build upon the success of AnyShare while providing a more secure and user-friendly experience. By leveraging the power of React and Firebase, we sought to create a robust platform that anyone could use without technical expertise.

## Features of FreeShare

1. **Nice and Pleasant UI**: FreeShare's user interface is designed to be visually appealing and easy to navigate, providing a delightful user experience.

2. **Upload and Download Files**: Users can effortlessly upload and share files, as well as download shared files using a 5-digit PIN.

3. **Free to Use**: FreeShare is completely free, ensuring that users can share files without any financial burden.

4. **No Email, SignUp, or Phone Number**: Privacy is a top priority, so FreeShare does not require users to provide personal information during the file-sharing process.

5. **Secure File Sharing**: Each file shared on FreeShare is associated with a unique 5-digit PIN, ensuring that only authorized users can access the files.

6. **Sharing Multiple Files**: FreeShare allows users to upload and share multiple files at once, making it more efficient for bulk sharing.

## The Technology Behind FreeShare

FreeShare utilizes a combination of technologies to provide a seamless and secure file-sharing experience:

1. **React**: The user interface of FreeShare is built using React, a popular JavaScript library for building user interfaces. React allows us to create interactive and dynamic components that make the platform easy to use.

2. **Firebase**: Firebase is a comprehensive platform provided by Google that offers various tools for building web and mobile applications. We use Firebase to store user data, including files and metadata, ensuring fast and reliable access to files.

## Working of FreeShare

The working of FreeShare involves several key steps, which we will explain in detail:

### Step 1: File Upload

When a user decides to share a file on FreeShare, they are presented with a file upload interface. Users have the option to upload a single file or multiple files simultaneously. We have implemented the DropzoneDialog from the Material-UI library to handle file uploads. Once the user selects the file(s) to upload, the upload process begins.

### Step 2: File Storage with Firebase Storage

All uploaded files are stored securely in Firebase Storage. Firebase Storage provides robust security measures, including encryption in transit and at rest, ensuring that user files are protected from unauthorized access.

### Step 3: Generating a Unique 5-Digit PIN

For each uploaded file, FreeShare generates a unique 5-digit PIN. This PIN acts as a secure identifier for the file and is required for users to download the shared files. To ensure uniqueness, we employ a recursive function that generates a random 5-digit PIN and checks if it already exists in the database. If it does, the function generates a new PIN until a unique one is found.

### Step 4: Storing Metadata with Firebase Realtime Database

The metadata associated with each shared file, including the download URL, timestamp, and unique PIN, is stored in Firebase Realtime Database. Firebase Realtime Database allows us to create a real-time sync with the frontend, providing instant updates and a seamless user experience.

### Step 5: Downloading and Sharing Files

To download a shared file, the recipient needs to enter the 5-digit PIN associated with that file. Upon entering a valid PIN, FreeShare retrieves the download URL from Firebase Realtime Database and opens the file in a new window for download. This process ensures that only authorized users can access the shared files.

## Code Explanation

Now, let's take a closer look at some of the main functionalities of the FreeShare platform and the corresponding code:

### File Upload and Progress Bar

```jsx
// File Upload and Progress Bar
const uploadFile = (file, filename) => {
    const storageRef = dbstorageref(storage, "images/" + filename);
    const uploadTask = uploadBytesResumable(storageRef, file);

    uploadTask.on(
      "state_changed",
      (snapshot) => {
        const progress = Math.round(
          (snapshot.bytesTransferred / snapshot.totalBytes) * 100
        );
        setPercentage(progress);
      },
      (error) => {
        console.error(error);
      },
      () => {
        getDownloadURL(uploadTask.snapshot.ref)
          .then((url) => {
            setDownloadUrl(url);
            console.log("File uploaded successfully");
            console.log("Download URL:", url);
            generateUniqueNumber()
              .then((uniqueNumber) => {
                console.log("Unique Number:", uniqueNumber);
                setUniqueID(uniqueNumber);
                return storeDataInDatabase(url, uniqueNumber, filename);
              })
              .then(() => {
                console.log("URL and Unique Number are stored in the database");
              })
              .catch((error) => {
                console.error("Error storing URL and Unique Number:", error);
              });
          })
          .catch((error) => {
            console.error(error);
          });
      }
    );
  };

```

The `handleFileDrop` function handles the file upload process. It uses the DropzoneDialog component from Material-UI to allow users to select and upload files. The progress bar displays the percentage of the file upload completion, providing real-time feedback to users.

In above code I have used Firebase Storage to upload the file . Initially I have initialzed the firebase storage references . To start the upload process , I have used `uploadBytesResumable` so that I will be able to display the percentage of the data or file uploaded and at the same time i have indicated that percentage in the progress bar.
If the upload is successfull then only url of the uploaded file be returned using function `getDownloadURL` . Then , a unique d will be created which will be shown to user.

### Generating a Unique 5-Digit PIN

```jsx
// Generating a Unique 5-Digit PIN
const generateUniqueNumber = () => {
  return new Promise((resolve, reject) => {
    const uniqueNumber = Math.floor(10000 + Math.random() * 90000);
    checkIfNumberExists(uniqueNumber)
      .then((exists) => {
        if (exists) {
          resolve(generateUniqueNumber());
        } else {
          resolve(uniqueNumber);
        }
      })
      .catch((error) => {
        reject(error);
      });
  });
};
```

The `generateUniqueNumber` function generates a unique 5-digit PIN for each uploaded file. It uses a recursive approach to check if the generated PIN already exists in the database. If it does, the function generates a new PIN until a unique one is found.

### Storing Metadata in Firebase Realtime Database

```jsx
// Storing Metadata in Firebase Realtime Database
const storeDataInDatabase = (url, uniqueNumber, filename) => {
  return new Promise((resolve, reject) => {
    const database = getDatabase();
    const databaseRef = ref(database, "fileData");
    const newDataRef = push(databaseRef);

    set(newDataRef, {
      url: url,
      unique: uniqueNumber,
      filename: filename,
    })
      .then(() => {
        toast.success("File Uploaded Successfully");
        setShowProgress(false);
        setshowshareUniqueID(uniqueNumber);
        setShowUniqueID(true);
        resolve();
      })
      .catch((error) => {
        reject(error);
      });
  });
};
```

The `storeDataInDatabase` function stores the metadata of the uploaded file, including the download URL, unique PIN, and filename, in Firebase Realtime Database. The function uses the `set` method provided by Firebase to add the data to the database.

### File Download and Deletion


```jsx
// File Download and Deletion
const downloadAndDeleteFile = async (downloadUrl, otp, filename) => {
  const filePath = "images/" + filename;
  const downloadWindow = window.open(downloadUrl, "_blank");
  const functions = getFunctions();
  const deleteFile = httpsCallable(functions, "Deletion");
  const response = await deleteFile({
    url: filePath,
    unique: otp,
  });
  console.log(response);
};
```

Cloud Function code for Deletion in cloud
```javascript
exports.Deletion = functions.https.onCall(async (data, context) => {
  try {
    const filePath = data.url;
    const password = data.unique;
    const db = admin.database();
    const fileRef = db.ref("fileData");
    const snapshot = await fileRef.once("value");
    const fileData = snapshot.val();

    const deleteRecord = async () => {
      const deletePromises = [];
      for (const [key, value] of Object.entries(fileData)) {
        if (password === value.unique) {
          deletePromises.push(fileRef.child(key).remove());
        }
      }
      await Promise.all(deletePromises);
    };

    setTimeout(async () => {
      try {
        await deleteRecord();
        await admin.storage().bucket().file(filePath).delete();
        console.log("File deleted from Firebase Storage:", filePath);
      } catch (error) {
        console.error("Error deleting file from Firebase Storage:", error);
      }
    }, 20000);

    return "Success";
  } catch (error) {
    console.error("Error scheduling file deletion:", error);
  }
});
```

The `downloadAndDeleteFile` function handles the file download and deletion process. Upon clicking the download button and providing a valid PIN, the function opens the file in a new window for download. Additionally, it
triggers the deletion of the file from both Firebase Realtime Database and Firebase Storage using a Firebase Cloud Function.

In the Cloud Functions code , whenever a reciever downloads the file it will trigger a cloud function which will be able to delet the file after 1 minute. This way it is ensured that privacy is maintained .
In `Deletion` function it will recieve two data one is **filePath** , which file to be deleted and **uniqueid** , it is used to find the Firebase Realtime Data Refrence of the file is pointed.  
This function will be invoked even if the User closes his or her browser or anything.



## Conclusion

In this Dev Blog, we've covered the development process and main functionalities of FreeShare, a free online file sharing platform. Using React and Firebase, we've built a user-friendly and secure platform that allows users to share files effortlessly with just a 5-digit code. We explored the code behind the platform and explained key functions responsible for file uploads, PIN generation, and file download and deletion.

We hope you enjoyed this Dev Blog and gained insights into how FreeShare works. Feel free to explore the platform yourself and share files with ease!

Happy sharing!

## References
- [Varshith V Hegde](https://github.com/Varshithvhegde)
- [Star 🌟 on Github](https://github.com/Varshithvhegde/FreeShare)
- [FreeShare](https://freeshare.vercel.app)