gpt4 book ai didi

node.js - 无法使用 GridFS 从 MongoDB 流式传输视频

转载 作者:行者123 更新时间:2023-12-05 05:50:46 26 4
gpt4 key购买 nike

我尝试了很长一段时间从 MongoDB 流式传输视频。阅读大量的 api 文档和示例就是无法让它工作

这是我的前端视频处理程序:

import { useState, useEffect } from "react";
import ReactPlayer from "react-player";

const CatVideos = () => {
const [videoList, setvideoList] = useState(null);
useEffect(() => {
const getVideos=async ()=> {
const response = await fetch('http://localhost:8000/cat-videos/videos');
const data = await response.json();
setvideoList(data);
console.log(data);
}
getVideos();
}, [])


return (
<div>
<h1>Cat videos</h1>
{videoList!=null && videoList.map((video)=>{
return <ReactPlayer key={video._id} url={'http://localhost:8000/cat-videos/videos/'+video._id}/>
})}
</div>
);
};

export default CatVideos;

后端流函数:

exports.getVideoStream = (req, res, next) => {
var id = req.params.id;
let gfs = Grid(conn.db, mongoose.mongo);
gfs.collection("videos");

gfs.files
.findOne({
_id: mongoose.Types.ObjectId(id),
})
.then((result) => {
const file = result;
if (!file) {
return res.status(404).send({
err: "Unavailable.",
});
}

if (req.headers["range"]) {
var parts = req.headers["range"].replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];

var start = parseInt(partialstart, 10);
var end = partialend ? parseInt(partialend, 10) : file.length - 1;
var chunksize = end - start + 1;

res.header("Accept-Ranges", "bytes");
res.header("Content-Length", chunksize);

res.header(
"Content-Range",
"bytes " + start + "-" + end + "/" + result.length
);
console.log(result.contentType)
res.header("Content-Type", result.contentType);
gfs.createReadStream({
_id: result._id,
range: {
startPos: start,
endPos: end,
},
}).readStream.pipe(res);

} else {
console.log("#################before####################");
res.header("Content-Length", result.length);
res.header("Content-Type", result.contentType);
console.log(result._id);
gfs
.createReadStream({
_id: result._id,
})
.pipe(res);
}
})
.catch((err) => {
res.json(err);
});
};

我确实从这个函数得到了响应,而且“Content-Type”似乎保持不变。

HTTP/1.1 206 Partial Content
X-Powered-By: Express
Access-Control-Allow-Origin: *
Accept-Ranges: bytes
Date: Thu, 23 Dec 2021 19:38:25 GMT
Content-Type: application/json; charset=utf-8
ETag: W/"2-vyGp6PvFo4RvsFtPoIWeCReyIC8"
Content-Range: bytes 0-1/2
Content-Length: 2

后端依赖:

"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.1",
"cors": "^2.8.5",
"ejs": "^3.1.6",
"express": "^4.17.2",
"gridfs-stream": "^1.1.1",
"method-override": "^3.0.0",
"mongodb": "^4.2.2",
"mongoose": "^6.1.2",
"multer": "^1.4.4",
"multer-gridfs-storage": "^5.0.2"
}

前端依赖:

    "axios": "^0.24.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-player": "^2.9.0",
"react-router-dom": "^6.2.1",
"react-scripts": "4.0.3",
"web-vitals": "^1.1.2"

最佳答案

我设法解决了这个问题。请注意,GridFSBucket 有一个默认的存储桶名称。查看 API 文档,它说它附加了存储桶名称“.files”。我的问题是我没有定义它并且下载流中的开始和结束没有正确定义导致错误。

您也可以使用它来流式传输图像、视频,只需更改前端的内容类型。非常通用的流。

exports.getVideoStream = (req, res, next) => {
mongodb.MongoClient.connect(url, function (error, client) {
if (error) {
res.status(500).json(error);
return;
}

// Check for range headers to find our start time
const range = req.headers.range;
if (!range) {
res.status(400).send("Requires Range header");
}

const db = client.db('videos');
// GridFS Collection
console.log(req.params.id);
db.collection('videos.files').findOne({_id:mongoose.Types.ObjectId(req.params.id)}, (err, video) => {
if (!video) {
res.status(404).send("No video uploaded!");
return;
}
// Create response headers
const videoSize = video.length;
const start = Number(range.replace(/\D/g, ""));
const end = videoSize - 1;

const contentLength = end - start + 1;
const headers = {
"Content-Range": `bytes ${start}-${end}/${videoSize}`,
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
"Content-Type": "video/mp4",
};

// HTTP Status 206 for Partial Content
res.writeHead(206, headers);

// Get the bucket and download stream from GridFS
const bucket = new mongodb.GridFSBucket(db,{bucketName:"videos"});

const downloadStream = bucket.openDownloadStream(video._id, {
start:start,
end:end
});

// Finally pipe video to response
console.log(streamCounter," start ",start," end ",end)
streamCounter++;
downloadStream.pipe(res);
});
});

};

关于node.js - 无法使用 GridFS 从 MongoDB 流式传输视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70466779/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com