He subido el archivo en mi sistema de filesystem backend usando multer
Mi servidor es un node y el cliente react .
Tengo problemas para descargar y mostrar el archivo guardado en la react del cliente
Cada vez que hago res.download(file) , simplemente arroja un error ya que la conexión se rechazó en el lado del cliente.
Mi código es el siguiente:
UserToUploadMapping.js
const mongoose = require("mongoose"); const UserToUploadMapping = new mongoose.Schema({ userId: { type:String, required:true }, file: { type: Object, required: true, }, date: { type: Date, default: Date.now, }, }); module.exports = mongoose.model("UserToUploadMapping", UserToUploadMapping);subirVideo.js
const router = require("express").Router(); const multer = require('multer'); const UserToUploadMapping = require('../models/UserToUploadMapping') let nameFile = '' const storage = multer.diskStorage({ destination:'./Videos', filename:(req,file,cb) => { console.log(file) nameFile = file.originalname + " "+ Date.now() cb(null, nameFile) } }) const upload = multer({storage:storage}) router.post('/upload', upload.single('video'), async (req,res,next) => { console.log("object") const saveMapping = new UserToUploadMapping({ userId:'123', file:req.file, }) await saveMapping.save() res.send("Video uploaded") }) router.get('/download', async(req,res,next) => { const x = await UserToUploadMapping.find() // res.send(x) res.download(x[0].path) }) module.exports = router;CLIENTE
const fetchVideo = async () => { const resp = await axios.get( "http://localhost:5000/api/user/video/download" ); console.log(resp) }; return ( <> <NavContainer /> <div className={classes.Post}> <Input type="file" onChange={(e) => uploadVideos(e.target.files)} accept="video/mp4" /> {/* <Button onClick={(e) => submitHandler(e)}>Upload</Button> */} <video></video> </div> </> );Error
Está ejecutando 2 aplicaciones Frontend y Backend con diferentes puertos (3000, 5000), por lo que los navegadores bloquean las solicitudes entre dominios. En Express, debe habilitar CORS para permitir la solicitud desde FrontEnd Url (http://localhost:3000).
Para la ruta de descarga, intente usar las funciones window.location en lugar de usar Axios .
Parece que puede tener un error tipográfico en su controlador de obtención ... está haciendo referencia a un elemento llamado 'ruta', pero eso no está declarado en su esquema
router.get('/download', async(req,res,next) => { const x = await UserToUploadMapping.find() // res.send(x) res.download(x[0].path)//<-Path Doesn't seem to be in the schema })Dado que no tiene un intento/captura en esa función, el error resultante podría estar desactivando su servidor, dejándolo no disponible.
Es posible que también desee echar un vistazo a esto para obtener más detalles sobre cómo descargar archivos usando axios
Hay algunos problemas dentro del archivo uploadVideo.js:
path de los datos, debe usar x[0].file.path(según cómo guarde el archivo en la base de datos)
const saveMapping = new UserToUploadMapping({ userId:'123', file:req.file, })uploadVideo.js y dónde ejecutamos la aplicación, debe usar una ruta absoluta al guardar archivos en el sistema.filename le dará nombres de archivo como este video.mp4 1622180824748 . Creo que esto es mejor "video-1622181268053.mp4" (tenemos la extensión de archivo correcta)Puedes consultar este código
const router = require("express").Router(); const multer = require('multer'); const UserToUploadMapping = require('../models/UserToUploadMapping') const path = require('path'); const uploadFolder = path.join(__dirname, "Videos"); // use a variable to hold the value of upload folder const storage = multer.diskStorage({ destination: uploadFolder, // use it when upload filename: (req, file, cb) => { // nameFile = file.originalname + " "+ Date.now() // --> give "video.mp4 1622180824748" let [filename, extension] = file.originalname.split('.'); let nameFile = filename + "-" + Date.now() + "." + extension; // --> give "video-1622181268053.mp4" cb(null, nameFile) } }) const upload = multer({ storage: storage }) router.post('/upload', upload.single('video'), async (req, res, next) => { const saveMapping = new UserToUploadMapping({ userId: '123', file: req.file, }) await saveMapping.save() res.send("Video uploaded") }) router.get('/download', async (req, res, next) => { const video = await UserToUploadMapping.find({}); res.download(video[0].file.path); // video[0].file.path is the absolute path to the file }) module.exports = router;Su código indica que está manejando archivos grandes (videos). Recomiendo encarecidamente considerar la separación de preocupaciones, no se recomienda manejar esto como parte de su otra lógica comercial según mi experiencia. Esto puede, por ejemplo, complicar las reglas del cortafuegos y la protección DDOS cuando sea necesario en el futuro.
Como mínimo, mueva la carga y descarga a su propio servidor, por ejemplo, 'files.yourappnamehere.com' para que pueda manejar los detalles por separado de su API de lógica comercial.
Si se ejecuta en la nube pública, le recomiendo encarecidamente que reutilice la funcionalidad de carga/descarga de blobs, permitiendo que sus clientes carguen directamente en el almacenamiento de blobs y también controlen las descargas directamente desde el almacenamiento de blobs, por ejemplo, en Azure, AWS o GCP.
Esto le ahorrará muchos de los detalles de implementación del manejo de archivos (muy) grandes, y también le brindará opciones de extensibilidad "gratuitas", como eventos al completar la carga del archivo.