视频上传在后端服务器上过早停止,但在本地主机上运行良好

问题描述 投票:0回答:1

我正在开发一个销售课程的 React 项目,当我尝试上传大于 1 GB 的视频文件时,上传过程总是中途停止。但是,其他小于该文件的文件上传没有任何问题。

我没有使用 AWS 或任何其他服务;我正在尝试将视频直接存储在我的后端服务器(Cyber Panel)上。 我该如何解决这个问题?我还在学习这个话题。

这是我在后端的代码

 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." });
  }
};
  

在前端

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>
)


}

像这样卡住了:截图

上传完整视频(失败)

net::ERR_CONNECTION_CLOSEDxhr

服务器端日志:
No files uploaded.

服务器没有上传限制。

javascript reactjs node.js database backend
1个回答
0
投票

看来您需要增加数据库超时才能收到响应。

© www.soinside.com 2019 - 2024. All rights reserved.