Video upload stops prematurely on backend server, but works well on localhost

I am working on a React project where I sell courses, and when I try to upload a video file larger than 1 GB, the upload process always stops midway. However, other files smaller than that upload without any issues.

I’m not using AWS or any other services; I’m trying to store the videos directly on my backend server (Cyber Panel).
How can I fix this? I’m still learning about this topic.

here is my code in backend

 export const uploadMultiplePelatihanVideo = async (req, res) => {
//   if (!req.files || !req.files.files) {
//     return res.status(400).json({ msg: "Tidak ada file yang diunggah." });
//   }

  const files = Array.isArray(req.files.files) ? req.files.files : [req.files.files];
  const allowedExt = [".mp4", ".avi", ".mkv"]; // Format video yang diizinkan
  const maxFileSize = 10000000000; // Batas ukuran file video 10000 MB
  const uploadedVideos = [];
  const title = req.body.title || "Tanpa Judul";

  try {
    const pelatihan = await Pelatihan.findOne({
      where: { pelatihanId: req.params.pelatihanId }
    });

    if (!pelatihan) {
      return res.status(404).json({ msg: "Pelatihan tidak ditemukan." });
    }

   
    // Loop melalui setiap file video yang diunggah
    for (const file of files) {
      const fileSize = file.data.length;
      const ext = path.extname(file.name);
      const fileName = uuidv4() + ext;
      const url = `${req.protocol}://${req.get("host")}/videos/pelatihan/${fileName}`;

      // Validasi ekstensi dan ukuran file
      if (!allowedExt.includes(ext.toLowerCase())) {
        return res.status(422).json({ msg: "Silakan unggah file video saja." });
      }

      if (fileSize > maxFileSize) {
        return res.status(422).json({ msg: `Ukuran file ${file.name} terlalu besar, maksimal 1000 MB.` });
      }

      // Pindahkan file video baru ke direktori
      await file.mv(`public/videos/pelatihan/${fileName}`, async (err) => {
        if (err) {
          return res.status(500).json({ msg: "Gagal memindahkan file video." });
        }

        // Simpan informasi video ke database
        const video = await VideoPel.create({
          pelatihanId: pelatihan.pelatihanId,
          urlVideo: url,
          title, // Judul video dari body atau default
          deskripsi: req.body.deskripsi || null,  // Deskripsi dari body atau null
        });

        uploadedVideos.push({
          fileName,
          url,
          videoId: video.videoPelId,
        });
      });
    }

    // Mengirimkan response setelah semua video berhasil diunggah
    res.status(200).json({
      msg: "Video pelatihan berhasil diunggah.",
      uploadedVideos, // Mengembalikan daftar video yang berhasil diunggah
    });
  } catch (error) {
    console.error("Error uploading video:", error);
    res.status(500).json({ msg: "Terjadi kesalahan pada server." });
  }
};
  

and in the frontend

export const uploadMultiplePelatihanVideo = async (files, id, onUploadProgress) => {
  const token = sessionStorage.getItem("authToken"); // Mendapatkan token otentikasi dari sessionStorage
  

  try {
    const response = await axios.post(
      `${API_URL}/pelatihan/${id}/upload-full-video`, 
      files, 
      {
        headers: {
          Authorization: `Bearer ${token}`, // Menyertakan token otentikasi
          "Content-Type": "multipart/form-data", // Mengatur tipe konten
        },
        onUploadProgress: onUploadProgress,
        timeout: 0, // Set timeout to 0 (no timeout)
      }
    );

    // Menampilkan notifikasi sukses menggunakan SweetAlert2
    Swal.fire({
      icon: "success",
      title: "Berhasil mengupload video",
      text: "Semua video telah berhasil diupload ke pelatihan.",
    });

    return response.data; // Mengembalikan data respons dari server
  } catch (error) {
    // Menampilkan notifikasi error menggunakan SweetAlert2
    Swal.fire({
      icon: "error",
      title: "Gagal mengupload video",
      text: error.response?.data?.msg || "Terjadi kesalahan, silakan coba lagi.",
    });

    throw error; // Lempar error agar bisa ditangani di tempat lain jika diperlukan
  }
};
function editPelatihan(){
const [previewVideos, setPreviewVideos] = useState([]);
const [uploadProgress, setUploadProgress] = useState(0);


const handleMultipleVideoSubmit = async (e) => {
  e.preventDefault();
  const { videoPel, title } = formVideo;

  if (videoPel.length === 0) {
    Swal.fire({
      icon: "warning",
      title: "Video pelatihan tidak ada",
      text: "Silakan unggah video pelatihan terlebih dahulu.",
    });
    return;
  }

  try {
    const videoFormData = new FormData();
    videoPel.forEach(file => videoFormData.append('files', file));
    videoFormData.append('title', title);

    await uploadMultiplePelatihanVideo(videoFormData, pelatihanId, (progressEvent) => {
      const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
      setUploadProgress(percentCompleted);
    });

    Swal.fire({
      icon: "success",
      title: "Video pelatihan berhasil diunggah",
      text: "Semua video pelatihan telah berhasil ditambahkan ke pelatihan.",
    });
    setFormVideo({ 
      videoPel: [],
      title: "", // Reset title setelah upload
    });
    setPreviewVideos([]);
    setUploadProgress(0); // Reset progress after upload
  } catch (error) {
    Swal.fire({
      icon: "error",
      title: "Gagal mengunggah video pelatihan",
      text: "Terjadi kesalahan saat mengunggah video pelatihan.",
    });
  }
};

return (
      <form className="space-y-4 mt-4">
          {/* Upload Video Pelatihan */}
          <div>
            <label htmlFor="videoPel" className="block text-sm font-medium text-gray-300">
              Upload Video Pelatihan
            </label>
            <input
              type="file"
              id="videoPel"
              name="videoPel"
              accept="video/*"
              multiple
              onChange={handleChange}
              className="mt-1 block w-full text-sm border border-gray-700 rounded-lg cursor-pointer text-gray-400 focus:outline-none bg-gray-700 placeholder-gray-400"
            />
            <input
              type="text"
              id="title"
              name="title"
              placeholder="Masukkan judul video"
              value={formVideo.title}
              onChange={handleChange}
              className="mt-1 block w-full text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
            />
            {previewVideos.length > 0 && (
              <div className="mt-2">
                {previewVideos.map((videoUrl, index) => (
                  <video key={index} src={videoUrl} controls className="mt-2 w-full max-h-64 object-cover rounded-md" />
                ))}
              </div>
            )}
            <button
              onClick={handleMultipleVideoSubmit}
              className="mt-2 bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded-lg"
            >
              Unggah Video Pelatihan
            </button>
          </div>
            <div className="mt-4">
              {uploadProgress > 0 && uploadProgress < 100 && (
                <div>
                  <progress value={uploadProgress} max="100" className="w-full" />
                  <span>{uploadProgress}%</span>
                </div>
              )}
            </div>
        </form>
)


}

Stuck like this: Screenshot

upload-full-video(failed)net::ERR_CONNECTION_CLOSEDxhr
Server side logs: No files uploaded.

The server has no upload limits.