New way of sharing files across devices over the web using WebRTC

Image for post
Image for post
Illustration by me 💚

There have been various methods of sharing files on the web. You upload a file to a server and share a link using which other people can download that file. While this is a tried-and-tested method of sharing data in general, let’s try to tackle this problem with a more “device-to-device” sharing approach rather than “device-server-device”.

Thinking about this problem, I kept coming back to technologies such as Bluetooth, NFC, WiFi-direct sharing. While I love these technologies, honestly they were a bit underwhelming in terms of speed, range and overall experience in general.

On the contrary, Web enjoys being connected to a global network and having access to the full potential of the internet speeds of the device. By implementing a better experience, I wondered if there was any way to combine the benefits of the web with file sharing ideologies of Bluetooth. I got excited when I learned about this underrated feature on the web that allows us to do exactly this and today I would like to share it with you 😄

WebRTC

So, putting it simply, the server helps in establishing the connection, but once the connection is established, it should no longer have access to the data shared between the connected devices.
Let’s try to implement a file-sharing mechanism between two devices with WebRTC. Since the original APIs of WebRTC make it tedious to implement the connection, I will be using a wrapper library — simple-peer, along with a tiny library download.js which makes it simple to initiate file download programmatically for the examples.

How WebRTC creates a connection (on a technical level)

Once we get the signal data of a peer, this data should be somehow sent to other nodes via a signaling server. The other nodes receive this data and try to establish a connection with the initiator. During this process, these nodes also generate their signal data and are sent to the initiator. The initiator receives this data and tries to establish a connection with the rest of the nodes.
And after this some cool magic…… Booooom……. Devices connected! ✨

A peer’s signal data can be accessed by listening to the signal event. To establish the connection using this signal data, other peers call signal() and pass the signal data as the argument. Example: somePeer.signal(peer1Data)

Don’t worry if you couldn’t get through the above workings of WebRTC and how simple-peer abstracts it. It confused the hell out of me when I just started dabbling around with WebRTC 😖. You’ll be fine in the upcoming sections.

Sharing a file with WebRTC (using simple-peer) 😎

The above code is deployed at https://file-sharing-example.netlify.com/webrtc

If you try the above code in the browser(or visit the deployed example) and select some image file(preferably below 100KB), you’ll see that it immediately downloads it. This is because the peers are in the same browser window and transfer is instantaneous. ⚡️

Now open the Console in the devtools, to check some cool stuff (shown in the image below). Notice the size property. The size of the data sent and received is the same. This shows that we were able to transfer the entire file in one go! 🎉

Image for post
Image for post
The file size is the same for sent and received files

Let’s start chunking the files 📦

Tiny files can be sent over WebRTC in one go, but for larger files, it is a good idea to divide our files into smaller chunks and send each chunk accordingly. Both ArrayBuffer and Blob objects have a slice function which makes this easier.

We keep chopping our array buffer, till there’s nothing left to chop! 🔪

Let’s discuss the implementation of chunking a little bit. The slice function takes a starting and ending byte position and returns a new array buffer which has a copy of all bytes in the given range. This new array buffer acts as a chunk. Then we update the existing array buffer by removing the chunk we separated earlier. This keeps going till we make our array buffer empty (i.e. chunked the entire file).

Now the question is what should be the size of each chunk? There’s no hard limit for this. Each browser has a little different implementation of WebRTC and data fragmentation internally. Some improvements in newer browsers don’t play well with older browsers 😑. From a lot of searching, I have come to assume that a safe max limit is 16KB for each chunk. Let’s add chunking to our existing code.

The above code is deployed at https://file-sharing-example.netlify.com/webrtc-chunking

If you try the above code(or view the deployed version), you should see there’s no difference in how the app works from the user’s end. But internally, we are now chunking and sending larger files too⚡️. Amaaaazing right?

Benefits of chunking

  • Large file size support — As mentioned earlier, this is the primary reason we implemented chunking.
  • A better way to interpret the amount of data transferred— By sending a file in chunks, we can now show the data such as percentage of file transferred, rate of file transfer, etc.
  • Detect incomplete file transfers — Situations, where a file could not be transferred completely, can now be caught and handled differently.

What’s next?

  • Signaling server — In the examples above, both receiver and sender were on the same browser window. This won’t happen(or I should say shouldn’t happen) in a real-life scenario. Hence, consider making it truly device-to-device using a signaling server.
  • Sharing multiple files — Sharing multiple files can be implemented easily based on the above examples.
  • Adding some fallback when WebRTC fails — When WebRTC connection fails, a different fallback method of file sharing can prevent the hassle of retrying connections.

Well, that’s it from me for today, WebRTC is much more than just file sharing, so I would encourage you to go deeper into it if you found this interesting 😄

On a side note, I have developed a full-fledged web app that uses WebRTC and WebSockets to share files across devices. It’s called Blaze ⚡️ and is open-source. I would love to see your contributions and feedback for the app. Share some ❤️ on it’s GitHub repo.

Written by

A student with a strong passion for web development and design, a 3D artist, and a YouTuber.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store