Storing Uploaded Files and Serving Them in Express

The first time I uploaded a file in Express and it actually worked…
I felt pretty good.
File reached the server.
Great.
Done.
Or so I thought.
Then the next question hit me.
Okay…
where did the file actually go?
And how do I access it again?
That was the part I hadn’t thought about.
Uploading is only half the story.
Storage and serving matter too.
And honestly…
that was when this topic started making sense.
My First Assumption Was Wrong
I thought:
Upload file.
Server has it.
Done forever.
Very vague thinking 😄
But files have to live somewhere.
Server has to store them.
And if users need access later…
you need a way to serve them.
That was the missing piece.
Where Uploaded Files Are Stored
In simple setups…
uploaded files often go into a folder on your server.
Something like:
uploads/
Very common.
Maybe:
project/
├── app.js
├── uploads/
And that folder holds uploaded files.
Simple.
That was my first setup.
Upload Storage Folder Structure
This Felt Like A Realization
Files weren’t floating around inside Express.
They were just stored on disk.
As actual files.
That sounds obvious now.
But I genuinely hadn’t thought of it that way early on.
Example Storage Setup
With Multer:
const upload=
multer({
dest:"uploads/"
});
This says:
Store incoming files in:
uploads/
Very straightforward.
And honestly…
good enough to begin.
Local Storage vs External Storage
This confused me by name.
Simple beginner view:
Local storage here means:
Files stored on your own server or machine.
Like the uploads folder.
External storage means:
Files stored somewhere outside your app server.
Separate storage services.
Different concept.
I didn’t go deep into that initially.
And honestly…
you don’t need to for understanding basics.
I Thought Local Storage Meant Browser Local Storage
Yes…
I made that mistake 😄
I heard “local storage” and thought of browser localStorage.
Different thing entirely.
Worth saying clearly.
I mixed them up once.
Then I Asked…
How do users actually access uploaded files?
If image exists in uploads folder…
how does browser see it?
That led me to static file serving.
And that was another “ohhh” moment.
Serving Static Files In Express
This is the pattern that made sense:
app.use(
"/uploads",
express.static(
"uploads"
)
);
At first I copied this without fully getting it.
Then I realized:
It maps a URL path…
to a folder.
That is the whole idea.
And once I saw that…
it felt simple.
Static File Serving Flow
Accessing Uploaded Files Via URL
Suppose file exists:
uploads/photo.jpg
And you have:
app.use(
"/uploads",
express.static(
"uploads"
)
);
Then file can be accessed at:
http://localhost:3000/uploads/photo.jpg
And honestly…
seeing that work felt satisfying.
Because full cycle now made sense.
Upload.
Store.
Access.
Done.
Static Files Took Me A Moment To Understand
The word “static” confused me.
It just means files served directly.
Like:
Images.
CSS.
Documents.
Files that don’t need route logic every time.
That’s enough to understand the idea.
Folder-Based Thinking Helped
I started picturing:
Request asks:
/uploads/photo.jpg
Express checks mapped folder.
Finds file.
Serves it.
Very simple.
That mental picture helped.
One Thing I Learned About Filenames
Be careful with filenames.
Very quickly I realized:
Two users may upload:
image.jpg
Now what?
Collision problem.
That is why unique names often matter.
I didn’t think about that initially.
Worth noting.
Safe File Handling Matters Too
This topic opened my eyes a bit.
Not every uploaded file should be trusted blindly.
Things I started hearing more:
Check file type.
Check file size.
Limit uploads.
Avoid accepting everything.
And honestly…
that makes sense.
Even at beginner level.
Example File Filter Idea
Conceptually:
Only allow images.
Reject other types.
That kind of thinking matters.
Even if you keep implementation simple at first.
One Mistake I Made
I thought storing files in uploads folder automatically made them public.
Not true.
Storage and serving are separate decisions.
That took me a little time.
Important distinction.
Another Mistake
I thought:
If I use express.static…
everything is safe automatically.
Not exactly.
You still think about what you expose.
That was another lesson.
Tiny Practice Setup
Create:
uploads/
Put:
test.jpg
Add:
app.use(
"/uploads",
express.static(
"uploads"
)
);
Open:
localhost:3000/uploads/test.jpg
That tiny exercise teaches a lot.
Honestly.
Why This Felt Like Completing The Picture
Before this…
I only understood upload step.
Now I understood:
Where file goes.
How file is served.
How users access it.
That made file handling feel complete.
Much more practical.
What Finally Made It Click
I stopped thinking:
Uploading is the whole feature.
And started thinking:
Uploading, storing, and serving are three parts of one flow.
That made everything connect.
That was the real shift.
Quick Recap
Uploaded files often go into a folder
Local storage means files stored on your server
Express can serve files with
express.static()Files can be accessed via URL
Safe file handling matters
Storage and serving are related but different
That’s the foundation.
Conclusion
At first I thought file upload was the hard part.
Turns out…
storing and serving files is just as important.
And honestly…
that is where the feature starts feeling complete.
Upload file.
Store it.
Serve it.
Access it.
That’s the core flow.
If you remember one thing from this article, remember this:
Uploading stores the file…
serving makes the file accessible.
That idea made it click for me.
If you like this simple learning-style explanation,
I write more notes at
devwithsahil.hashnode.dev
and share progress on LinkedIn 🙂



