所以这很奇怪。
我正在运行带有角度,节点和护照的应用程序。 它管理一些信息,您可以查看与之相关的视频。
当我在浏览器中使用该应用程序时,一切似乎都正常。但是当我使用Android手机浏览器访问应用程序(没有用iOS测试)时,我可以登录并且一切正常,但是当我访问视频时(在同一个会话中!),护照拒绝访问!我很困惑,因为其他应用程序在Android浏览器中工作正常......
路线:
app.all('*',ensureAuthenticated)
app.get('/ping', routes.ping)
app.get('/logout', routes.logout)
app.get('/start', routes.start)
#more routes
app.get('/videos/:name', can_view_video, media.play) #can_view_video checks if a user has the rights to see the video
#Middleware to check that a user is authenticated
ensureAuthenticated = (req, res, next) ->
if (req.isAuthenticated())
return next()
logger.debug("Not authenticated!")
res.redirect('/')
#Middleware to check that user can view video
can_view_video = (req, res, next) ->
url = req.url
url_params_only = url.substring("/videos/".length)
id = url_params_only.substring(0, url_params_only.indexOf("/"))
can_access(req, res, id, (err) ->
if err?
handle_error(err, err.message, res)
else
return next()
)
can_access = (req, res, id=null, next) ->
role = req.user.role
if id is null
id = req.params.userId
user_id = req.user.id
User.findOne({ user_id:id }, (err, user) ->
if err?
handle_error(err, err.message, res)
if not user?
text = "no user with that id"
handle_error(err, text, res)
else if not id == user_id or role is not "admin"
text = "no user with that id"
logger.debug(text)
handler_error(new Error(text), text, res)
else
logger.debug "Login: can access, ok"
next()
)
播放视频:
exports.play = (req,res) ->
video_path = __dirname + "/media/" + req.user.id + "/" + req.params.video
fs.readFile(video_path, (err, data) ->
if err?
handle_error(err, "video can't be read", res)
else
range = req.headers.range
if range?
total = data.length
parts = range.replace(/bytes=/, "").split("-")
partialstart = parts[0]
partialend = parts[1]
start = parseInt(partialstart, 10)
end = if partialend then parseInt(partialend, 10) else total-1
chunksize = (end-start)+1
res.writeHead(206,
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": 'video/mp4' )
else
logger.debug("no range")
res.writeHead(200,
"Content-Length": data.length,
"Content-Type": 'video/mp4')
res.end(data)
)
使用Android浏览器访问时的输出是:
no range
Not authenticated!
编辑:如果我删除了护照身份验证,视频可以显示在手机上......
EDIT2:根据要求:序列化函数
passport.serializeUser((user, done) ->
done(null, user._id)
)
passport.deserializeUser((id, done) ->
User.findById(id, (err, user) ->
done(err, user)
)
)
所以看起来代码运行正常,视频被加载并返回到浏览器,但它无法播放任何奇怪的原因,这对我来说非常令人费解......
在普通的桌面浏览器(例如Chrome)中,我在标题中获得了一个范围,然后视频返回并播放 - 没有"未经过身份验证!"消息!
答案 0 :(得分:0)
res.writeHead(206,
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": 'video/mp4' )
...
res.end(data)
我们在这里告诉标题我们发送了一个块,但实际上是在发送整个文件......
从here我找到了正确的方法:
res.end(data.slice(start, end+1), "binary");
这似乎改善了很多事情,但我们需要进一步检查