You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于MERN Stack实现无第三方包的MongoDB Atlas文件上传?

Got it, let's walk through how to implement file uploads to MongoDB Atlas using only the MERN stack tools you specified (no extra third-party packages beyond express, react, node, mongodb, and axios). I'll break this down into backend and frontend code with explanations:


Backend Implementation (Node.js + Express + MongoDB)

1. Initialize Project & Install Dependencies

First, set up your backend project and install the allowed packages:

mkdir mern-file-upload-backend
cd mern-file-upload-backend
npm init -y
npm install express mongodb cors

2. Set Up Server & MongoDB Connection

Create a server.js file. We'll connect to MongoDB Atlas, and use a collection to store file metadata + Base64-encoded file content (great for smaller files; I can share a GridFS version for larger files if needed):

const express = require('express');
const { MongoClient, ObjectId } = require('mongodb');
const cors = require('cors');

const app = express();
app.use(cors());
// Increase JSON limit to handle larger Base64 strings (adjust as needed)
app.use(express.json({ limit: '10mb' }));

// Replace with your MongoDB Atlas connection string
const mongoURI = 'mongodb+srv://<your-username>:<your-password>@cluster0.mongodb.net/?retryWrites=true&w=majority';
const client = new MongoClient(mongoURI);

let db;
let filesCollection;

// Connect to MongoDB
async function connectDB() {
  try {
    await client.connect();
    db = client.db('fileUploadDB'); // Your database name
    filesCollection = db.collection('files'); // Collection to store files
    console.log('Connected to MongoDB Atlas');
  } catch (err) {
    console.error('MongoDB connection error:', err);
  }
}

connectDB();

// Upload endpoint
app.post('/api/upload', async (req, res) => {
  try {
    const { fileName, fileType, fileData } = req.body;

    if (!fileName || !fileType || !fileData) {
      return res.status(400).json({ message: 'Missing file details' });
    }

    // Optional: Add file type validation here (e.g., only allow images/PDFs)
    const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
    if (!allowedTypes.includes(fileType)) {
      return res.status(400).json({ message: 'Invalid file type' });
    }

    // Insert file into MongoDB
    const result = await filesCollection.insertOne({
      fileName,
      fileType,
      fileData,
      uploadedAt: new Date()
    });

    res.status(201).json({
      message: 'File uploaded successfully',
      fileId: result.insertedId
    });
  } catch (err) {
    console.error('Upload error:', err);
    res.status(500).json({ message: 'Failed to upload file' });
  }
});

// Fetch file endpoint
app.get('/api/files/:fileId', async (req, res) => {
  try {
    const file = await filesCollection.findOne({ _id: new ObjectId(req.params.fileId) });

    if (!file) {
      return res.status(404).json({ message: 'File not found' });
    }

    res.json(file);
  } catch (err) {
    console.error('Fetch error:', err);
    res.status(500).json({ message: 'Failed to fetch file' });
  }
});

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Don't forget to replace <your-username> and <your-password> with your MongoDB Atlas credentials.


Frontend Implementation (React + Axios)

1. Initialize React Project & Install Axios

Set up your React app and add axios for API calls:

npx create-react-app mern-file-upload-frontend
cd mern-file-upload-frontend
npm install axios

2. Create File Upload Component

Replace src/App.js with this component that handles file selection, Base64 conversion, upload, and download:

import { useState } from 'react';
import axios from 'axios';

function App() {
  const [selectedFile, setSelectedFile] = useState(null);
  const [uploadStatus, setUploadStatus] = useState('');
  const [fileId, setFileId] = useState('');

  // Convert file to Base64 string
  const convertToBase64 = (file) => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result.split(',')[1]); // Strip data URI prefix
      reader.onerror = (error) => reject(error);
    });
  };

  // Handle file selection
  const handleFileChange = (e) => {
    setSelectedFile(e.target.files[0]);
    setUploadStatus('');
    setFileId('');
  };

  // Handle upload to backend
  const handleUpload = async () => {
    if (!selectedFile) {
      setUploadStatus('Please select a file first');
      return;
    }

    try {
      setUploadStatus('Uploading...');
      const fileData = await convertToBase64(selectedFile);

      const response = await axios.post('http://localhost:5000/api/upload', {
        fileName: selectedFile.name,
        fileType: selectedFile.type,
        fileData: fileData
      });

      setUploadStatus('File uploaded successfully!');
      setFileId(response.data.fileId);
    } catch (err) {
      setUploadStatus('Failed to upload file. Please try again.');
      console.error('Upload error:', err);
    }
  };

  // Handle downloading the uploaded file
  const handleDownload = async () => {
    if (!fileId) {
      setUploadStatus('No file uploaded yet');
      return;
    }

    try {
      const response = await axios.get(`http://localhost:5000/api/files/${fileId}`);
      const { fileName, fileType, fileData } = response.data;

      // Convert Base64 back to blob and trigger download
      const blob = new Blob(
        [Uint8Array.from(atob(fileData), c => c.charCodeAt(0))],
        { type: fileType }
      );
      const url = window.URL.createObjectURL(blob);
      const downloadLink = document.createElement('a');
      downloadLink.href = url;
      downloadLink.download = fileName;
      document.body.appendChild(downloadLink);
      downloadLink.click();
      window.URL.revokeObjectURL(url);
      document.body.removeChild(downloadLink);

      setUploadStatus('File downloaded successfully!');
    } catch (err) {
      setUploadStatus('Failed to fetch file. Please try again.');
      console.error('Download error:', err);
    }
  };

  return (
    <div className="App" style={{ padding: '2rem', maxWidth: '600px', margin: '0 auto' }}>
      <h1>MERN File Upload to Atlas</h1>
      <input
        type="file"
        onChange={handleFileChange}
        style={{ margin: '1rem 0' }}
        accept=".jpg,.png,.pdf" // Restrict file types (matches backend validation)
      />
      <button onClick={handleUpload} style={{ padding: '0.5rem 1rem', marginRight: '1rem' }}>
        Upload File
      </button>
      {fileId && (
        <button onClick={handleDownload} style={{ padding: '0.5rem 1rem' }}>
          Download Uploaded File
        </button>
      )}
      {uploadStatus && <p style={{ marginTop: '1rem', color: uploadStatus.includes('success') ? 'green' : 'red' }}>{uploadStatus}</p>}
    </div>
  );
}

export default App;

Key Notes

  • File Size Limits: MongoDB documents have a 16MB default limit. Since Base64 increases size by ~33%, this setup works for files up to ~12MB. For larger files, I can share a GridFS implementation using the official MongoDB driver (no third-party packages needed).
  • Security: The backend includes basic file type validation – expand this to match your use case. Also, ensure your Atlas user has read/write permissions to your database.
  • CORS: The backend uses the cors package (allowed per your request) to enable cross-origin requests from the React frontend.

内容的提问来源于stack exchange,提问作者sheepsbleat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 11:37:54