Building an upload backend service with No libraries, No forms, just vanilla JS with progress)

Sdílet
Vložit
  • čas přidán 2. 06. 2024
  • OK, I lied I used the HTTP and the fs library on node js but nothing on the backend but nothing but the built-in functions on the browser.
    In this video, I’ll build a simple progressor upload service and explain how it works. Let us have fun.
    Source Code
    github.com/hnasr/javascript_p...
    Resources
    nodejs.org/api/http.html#http...
    developer.mozilla.org/en-US/d...
    developer.mozilla.org/en-US/d...
    0:00 Intro
    3:00 Preparing Frontend/Backend
    7:00 Reading file with FileRead in Frontend
    14:00 Slicing the file into Chunks
    19:00 Sending Chunks through fetch to Backend
    23:00 Received Chunks on Backend
    28:00 Progress on Frontend
    30:00 Increase chunk size
    31:00 Possible Improvement and Scalability
    '
    Become a Member on CZcams
    / @hnasr
    🔥 Members Only Content
    • Members-only videos
    Support my work on PayPal
    bit.ly/33ENps4
    🧑‍🏫 Courses I Teach
    husseinnasser.com/courses
    🏭 Backend Engineering Videos in Order
    backend.husseinnasser.com
    💾 Database Engineering Videos
    • Database Engineering
    🎙️Listen to the Backend Engineering Podcast
    husseinnasser.com/podcast
    Gears and tools used on the Channel (affiliates)
    🖼️ Slides and Thumbnail Design
    Canva
    partner.canva.com/c/2766475/6...
    🎙️ Mic Gear
    Shure SM7B Cardioid Dynamic Microphone
    amzn.to/3o1NiBi
    Cloudlifter
    amzn.to/2RAeyLo
    XLR cables
    amzn.to/3tvMJRu
    Focusrite Audio Interface
    amzn.to/3f2vjGY
    📷 Camera Gear
    Canon M50 Mark II
    amzn.to/3o2ed0c
    Micro HDMI to HDMI
    amzn.to/3uwCxK3
    Video capture card
    amzn.to/3f34pyD
    AC Wall for constant power
    amzn.to/3eueoxP
    Stay Awesome,
    Hussein
  • Věda a technologie

Komentáře • 95

  • @_quick-math
    @_quick-math Před 2 lety +35

    Please never stop doing this "from scratch" videos! They are super helpful and I love learning more about this from your videos.

  • @greatnile
    @greatnile Před 2 lety +51

    never judge a book by its cover!
    the first moment I saw the title of the video I felt disappointed🤦🏽‍♂️ as you are known by the low-level guy (at least for me) and I thought you gonna do the same video that everyone on the internet record right now 😀. to be honest I totally regreted that feeling after 2 or 3 minutes 😀.
    thank you. this is an eye opener.
    I would suggest that you keep building on top of this and make another video for building the distributed stateless upload service. and from the frontend side you can utilize some DS concepts like queue to receive the chunks and release/send them in a controlled manner.
    it could also be nice to explain the similarities between this approach and the native multipart/form-data.
    again, thanks a million for all of your amazing content. 😍

    • @josephmakram4342
      @josephmakram4342 Před 2 lety +5

      😂 😂 same fealing when i read the title

    • @MadAndy24
      @MadAndy24 Před 2 lety +2

      Actually I thought the exact opposite, this is one of Hussain's best videos! Usually he tends not to go into as much depth as I'd like to see. Here he builds the whole example, and equally importantly covers its deficiencies and options for improving and scaling it.

    • @greatnile
      @greatnile Před 2 lety

      @@MadAndy24 I also think it is one of the best videos, but what I am saying is, it wasn't my first thought when reading the title only.

  • @abhishekanantharam645
    @abhishekanantharam645 Před 2 lety +29

    You channel is a goldmine, thanks!

  • @FadlySansan
    @FadlySansan Před 2 lety +6

    This is nice continuity from node http and node fetch! Thank you, I learned a lot from your contents

  • @mitulp236
    @mitulp236 Před 2 lety +3

    OMG😱, This is amazing, loving your content Hussain

  • @denilsoncosta9837
    @denilsoncosta9837 Před 2 lety +5

    I always use form data to upload a file, but this way is more scalable and give you more control. I will wait more videos like this one.

  • @JyotinderSingh
    @JyotinderSingh Před 2 lety

    This is a really valuable video. Not just because you show how to build an upload service with vanilla JS but also because of the last 10 mins where you explain how one can take it forward. Thanks Hussein!

  • @njayman
    @njayman Před 2 lety

    I started learning api from express ignoring the core nodejs modules. Now i see how important this was for me to learn all these. Thanks a lot for this video.

  • @borisc5357
    @borisc5357 Před 2 lety

    Great stuff! Something that I've been looking at, but with multiple file upload and directories. I like the commentary about scalability, though a database seems like overkill

  • @UIGems
    @UIGems Před rokem +2

    Thanks! Amazing video... I really enjoyed to the core! Gave me insight and motivation to learn more :)

  • @gabrieljose7041
    @gabrieljose7041 Před 2 lety +1

    Awesome video, we need more content like this. If you think that is a good idea i'll love to see another video doing this in the "right way" or at least the way you explain in the ending of the video!!!

  • @subhamprasad1373
    @subhamprasad1373 Před 2 lety +2

    I was waiting for this video... Thank you

  • @jcollins519
    @jcollins519 Před 2 lety

    You have no idea how helpful it is that you mention "this is a custom header". So many guys forget to identify built-in/belonging-to-some-api-specification vs custom in many respects of programming

  • @Flankymanga
    @Flankymanga Před 2 lety

    i was not previously interested in node.js but seeing Hussein videos - i am starting to catch a glimpse...

  • @fuadcs22
    @fuadcs22 Před rokem

    Many of my friends complains that your videos are too lengthy and you speak too slowly, but I always say to them that your videos are like watching movies which are full of knowledge and fun.

  • @talalnajam481
    @talalnajam481 Před 2 lety

    Hands down one of the best (if not the best) channels on youtube

  • @mohammadsalah4736
    @mohammadsalah4736 Před 2 lety

    Amazing video. This video would have saved me a lot of time of searching a year ago

  • @Porkchop137
    @Porkchop137 Před 2 lety

    you make such good content!
    but I swear, the spaces in your html attributes trigger my fight or flight!
    keep up the great work 👍

  • @the_full_stack_junkie
    @the_full_stack_junkie Před 2 lety

    Great video thanks so much would love more videos like this

  • @udorblessing
    @udorblessing Před 2 lety

    This is absolutely amazing

  • @nirajkhatiwada6696
    @nirajkhatiwada6696 Před 2 lety +1

    This one is too funny and knowledgeable. I love it.

    • @annyni6640
      @annyni6640 Před 2 lety

      right? I was watching this with headphones inside a college building. People probably thought I was crazy laughing at a coding video

  • @matthewfala
    @matthewfala Před 2 lety

    Too late for me to watch rn. Putting in my watch queue for later. Thanks for awesome content!

  • @vfryhn2
    @vfryhn2 Před 2 lety +11

    This is amazing, could you please show how multipart-form work?
    Thank you for your content

    • @hnasr
      @hnasr  Před 2 lety +13

      Good question, I suppose I should have started with that☺️

  • @user-mo3cw6go7c
    @user-mo3cw6go7c Před 2 lety

    A beautiful guide
    I'm lucky I subscribed to your channel
    My friend

  • @lucaswerlemelz9502
    @lucaswerlemelz9502 Před rokem

    this was so fun

  • @rohangaonkar8912
    @rohangaonkar8912 Před 2 lety

    You videos are awesome. One question, you are sending res back even before chunks are actually appended to the file. Is it fine?

  • @EzequielRegaldo
    @EzequielRegaldo Před 2 lety

    Awesome ! Just AWESOME

  • @yannistheodorakopoulos5916

    Hello Hussein,
    Thank you for the content. Amazing as always.
    Is the server able to make any other operations while writing each chunk to the file?

    • @hnasr
      @hnasr  Před 2 lety +4

      Fantastic question ! In my code no since I am using AppendSync which uses the main thread. Using Append (async) will use the thread pool and the server will be free to serve other requests/do other tasks.
      We are obviously talking about nodejs here. Other runtimes/languages are completely different story.

    • @yannistheodorakopoulos5916
      @yannistheodorakopoulos5916 Před 2 lety

      @@hnasr Thank you for the response Hussein.
      Just out of curiosity, is it safe to use Append (async) though? Was considering what's going to happen if for any reason the chunks are getting processed in a different order.

    • @haidoan89
      @haidoan89 Před 2 lety

      @@yannistheodorakopoulos5916 if you really want to upload large files frequently, then its better to scale your uploading services as he recommend at the end of video.

  • @gillfromamritsar
    @gillfromamritsar Před 2 lety

    beautiful stuff

  • @abdhelal
    @abdhelal Před 2 lety +1

    Great video 👍.
    I have a question is it guarantee that chunks will arrive in the same order that were sent since you are appending them in the backend. In a sense this could lead to corrupted file if they didn't arrive in the same order

    • @hnasr
      @hnasr  Před 2 lety +4

      In this particular example I am sending them in order and serially. I don’t send a chunk unless I get a response from the server that the previous chunk arrived. (The await in the loop)
      If I started sending chunks in parallel them we are the mercy of both the frontend queuing and the backend queue. That is where we will need each chunk to have a unique and sequential id at layer 7 so we can assemble it

  • @SahilPatel-zn3lo
    @SahilPatel-zn3lo Před 9 měsíci

    This is really a valuable video and you made it in a way that anyone can take this and implement their own upload service logic of any scale.... I love that .... There is one question i have though about the resumability part that we can an endpoint in backend right to check where we left off like you mentioned that chunk id from that we can send that chunk id to frontend and continue upload from that can we not? or maybe i am missing something please do tell me

  • @chris94kennedy
    @chris94kennedy Před 2 lety

    Thank you for your content

  • @driziiD
    @driziiD Před 2 lety

    brilliant, thank you sir

  • @andrzejsupermocny2386
    @andrzejsupermocny2386 Před 2 lety +4

    Why chunk at all if TCP itself chunks?

    • @hnasr
      @hnasr  Před 2 lety +3

      Valid question. If we were using raw TCP directly, the os would have broke the data into TCP segments each based on the window size.
      However, we are using HTTP which does use TCP except we don’t have that low level control. The proxies and servers have all sorts of protection at HTTP layer to timeout large requests.

    • @andrzejsupermocny2386
      @andrzejsupermocny2386 Před 2 lety +1

      @@hnasr Thanks. Is `multipart/form-data` somehow immune from this kind of protection?

  • @buddhanag4987
    @buddhanag4987 Před 2 lety

    Very informative

  • @austinchan452
    @austinchan452 Před 2 lety

    Thanks for the great video! One question, how would you decide whether to use client-side upload to S3 or server-side upload S3? I'm thinking that at a smaller team, do we really need a upload service or we can just get the presigned url and upload to S3 directly from client side.

    • @haidoan89
      @haidoan89 Před 2 lety

      if you want to upload from client to s3, then its needed to put s3 config in the client. I am not sure its good idea.

    • @davidnaiz2417
      @davidnaiz2417 Před 2 lety +1

      @hai doan
      Using presigned url, You don't have to put any secret info on the client. The server shouldn't be involved in the upload process at all. Only store the url in db.

    • @haidoan89
      @haidoan89 Před 2 lety

      @@davidnaiz2417 thanks for your info, btw uploading fron backend will be good for scale, especially uploading large image by chunk.

  • @jlsuncin
    @jlsuncin Před 2 lety +1

    const chunkCount = Math.ceil(ev.target.result.byteLength/CHUNK_SIZE) // That rounds a number up to the next largest integer, by example 3001/1000 -> 3.001 -> 4

  • @trueishere8302
    @trueishere8302 Před 2 lety

    Great content....

  • @seephor
    @seephor Před 2 lety

    Beautiful little example. You wonder why these open source upload libraries are several MEGABYTES of code and that’s just client code.

  • @rishiagrawal812
    @rishiagrawal812 Před 2 lety

    This is a really awesome tutorial.
    But nowadays we generally upload these files to cloud storage (like Google files storage, AWS file storage). In then we upload in one request or do me do multiple requests.
    Is there any good article to go though it

  • @winken2666
    @winken2666 Před 2 lety

    Cool, thanks!

  • @mdshariffoysalshoron1345

    This was an amazing video, it's helps me a lot. could you please show how to upload more that 2 GB file?

  • @denilsoncosta9837
    @denilsoncosta9837 Před 2 lety

    how can i get more information about this topic, transfer bytes via network?

  • @MaJinSu
    @MaJinSu Před 2 lety

    I love it

  • @VIDEO-pg8ns
    @VIDEO-pg8ns Před 2 lety

    Superb 📁📁📁
    can u make a video on downloading files from server to client

  • @ismail-talb
    @ismail-talb Před 2 lety

    nice video

  • @bashardlaleh2110
    @bashardlaleh2110 Před 2 lety +1

    is this what an html form does when you upload a file ?

  • @mtnrabi
    @mtnrabi Před 2 lety +3

    Great content!!
    Do you have a guess for why onprogress event doesn’t let us access the bytes it read?
    I mean it’s already reading it in chunks, and using the onload event and chunking it afterwards I really feel stupid and wasteful.
    Really can’t tell why, and I’m curious for your guess on the matter
    And again - really really great vid. Good developers will appreciate all this vanilla stuff that is going on here.

    • @soniablanche5672
      @soniablanche5672 Před 2 lety

      It's most likely a security thing

    • @ichizos9615
      @ichizos9615 Před 2 lety

      Was thinking about that also and I suspect that it would be more troublesome if it would behave like that. Remember FileReader can prompt an error (description from moz):
      "The error event is fired when the read failed due to an error (for example, because the file was not found or not readable)" and now imaging reading and streaming an invalid file (which you don't know its invalid) to the server just to notice that at 98% there is an issue. Now you would have to code a logic to remove all the data from the server and you would waste the connection, transfer and space.
      It's simpler for the browser to check and validate the file from the user on their own device *locally* and when it's valid FIleReader gives a code or developer a green light to work with the file.

  • @tdsora
    @tdsora Před 2 lety

    how would you do it so that you don't have to load the entire file into memory first? save a fixed size into the array buffer, upload them all, then replace the array buffer with the next bytes of the file, and so on...?

  • @orhn
    @orhn Před 2 lety

    1- Speaking of scalable backend, how does backend knows if the upload ended if you can just send the next request to another server?
    2- Why does completety different fetch request handled by single req.on(“data”) on backend? I mean How does backend know those are the part of the same file ?

  • @ikumargaurav
    @ikumargaurav Před rokem

    Is there any possibility that chucks are received in different order ??

  • @ghaithshaal1426
    @ghaithshaal1426 Před 2 lety

    More like this please ! Thank you

  • @rabbyhossain6150
    @rabbyhossain6150 Před 2 lety +1

    Best video on file upload?

  • @yadneshkhode3091
    @yadneshkhode3091 Před 2 lety +3

    Hello Hussein
    Can you please make a detailed video on how to process 2gb file on 1 gb ram etc
    Also if possible you can make paid courses for system design from absolute basics to Hussein Nasser level

  • @code2287
    @code2287 Před rokem

    How do you account for this in a real life application having multiple users assuming they would be duplicate names thereby causing chunks get attached to different data..how would you handle creating unique names in the backend or front

  • @ramanjay14
    @ramanjay14 Před 2 lety

    In order to read file in the chunk, instead of passing theFile blob, use slice on the theFile and then read it via filereader.
    ```
    const f_chunk = theFile.slice(chunkId*CHUNK_SIZE, (chunkId+2)*CHUNK_SIZR)
    const filereader = new FileReader ();
    filereader.onload = ev = { sendChunkToServer(ev.target.result)}
    filereader.readAsArrayBuffer(f_chunk);
    ```

  • @exe.m1dn1ght
    @exe.m1dn1ght Před 6 měsíci

    26:26 why you are blocking the main thread with read Sync ?

  • @evgenylevchenya8734
    @evgenylevchenya8734 Před 2 lety

    Hi, Hussein. What do you think about gun.js?

  • @johnm8358
    @johnm8358 Před 2 lety

    Nice tutorial... But I think you should take it one step further to implement what u Suggest at the end

  • @fawazsullia5620
    @fawazsullia5620 Před 2 lety

    Idk why, but for me the image doesnt display in vscode. Says it's in some unsupported format

  • @danishkha998172
    @danishkha998172 Před 2 lety

    Awesome

  • @jlambert12013
    @jlambert12013 Před 2 lety

    I search how to do this without libraries for hours. Thanks!

  • @jasonlrydberg6101
    @jasonlrydberg6101 Před rokem

    I haven't watch the whole video yet but im building in this type of function for a clientt but im wondering if this will this be secure enought so that my client wont be hacked or get in virus on his computer true the file. 🤔

  • @bibhasash7371
    @bibhasash7371 Před rokem

    what if the chunk count of chunk value is in float?

  • @driziiD
    @driziiD Před 2 lety

    lol the Japanese making it hit different 😁

  • @artwriter7377
    @artwriter7377 Před 2 měsíci

    amazing content. does anyone know other resources like this where we get to see things from scratch and not very advance to keep up with

  • @brymstoner
    @brymstoner Před rokem

    i'm uploading to nowhere. the upload completes but doesn't appear anywhere.

  • @heitorthewizard
    @heitorthewizard Před rokem

    at the file name creation, you could've used the new Date() instead of Math.random().

  • @prashanttripathi1738
    @prashanttripathi1738 Před 2 lety

    I developed same solution for a company as a scalable & resumable file upload service, they didnt give a shit.

  • @coolkidllama1483
    @coolkidllama1483 Před 2 lety

    browsers dont use require how tf can i do a file upload

  • @ZelenoJabko
    @ZelenoJabko Před 2 lety

    I think your code is vulnerable to the directory traversal attack.

  • @PiyushChauhan2011
    @PiyushChauhan2011 Před 2 lety

    Solid stuff from scratch 🔥
    Aside from this content I have interest in learning about postgres write ahead log and change data capture stuff and publishing changes to message broker e.g. rabbitmq

  • @ZelenoJabko
    @ZelenoJabko Před 2 lety +1

    Your chunk count formula is wrong. It has the potential to send one empty chunk at the end.

    • @MadAndy24
      @MadAndy24 Před 2 lety +1

      Yup, rather than just adding one, you should round the chunk count up.

    • @ZelenoJabko
      @ZelenoJabko Před 2 lety

      @@MadAndy24 or add chunk_size - 1 before dividing

  • @ripudamank
    @ripudamank Před rokem

    Better way for unique name is append a timestamp

  • @pss_crs
    @pss_crs Před 2 lety

    Js is just script for form validation not language but standing its nature.