停止用户从服务器下载文件 - JWPlayer + Coldfusion
问题描述:
我有一个应用程序,我使用wowza服务器和hdfvr进行视频录制。我使用jwplayer在网站上播放视频。停止用户从服务器下载文件 - JWPlayer + Coldfusion
我需要知道如何停止用户下载mp4文件。目前我正在使用认证后返回媒体流的Coldfusion。这是返回mp4内容的文件代码部分。
<cfif FileExists(videoPath)>
<cfset fileInfoVar = GetFileInfo(videoPath)>
<cfheader name="Last-Modified" value="#fileInfoVar.Lastmodified#">
<cfheader name="ETag" value="#hash(videoPath, 'MD5')#">
<cfheader name="Content-Location" value="https://example.com/videoreturnfile.cfm">
<cfif structKeyExists(GetHttpRequestData().headers, 'Range')>
<cfset rangeDownload(videoPath)>
<cfelse>
<cffile action="readbinary" file="#videoPath#" variable="theData">
<cfscript>
context = getPageContext();
context.setFlushOutput(false);
response = context.getResponse().getResponse();
response.setContentType("video/mp4");
response.setContentLength(arrayLen(theData));
out = response.getOutputStream();
out.write(theData);
out.flush();
out.close();
</cfscript>
</cfif>
</cfif>
<cffunction name="rangeDownload" returnType="void" output="yes">
<cfargument name="file" type="string" required="true" hint="path to file">
<cfset var l = {}>
<cfset l.request = GetHttpRequestData()>
<cffile action="readbinary" file="#ARGUMENTS.file#" variable="l.theData">
<cfset l.size = arrayLen(l.theData)>
<cfset l.length = l.size>
<cfset l.start = 0>
<cfset l.end = l.size - 1>
<!--- Now that we've gotten so far without errors we send the accept range header
/* At the moment we only support single ranges.
* Multiple ranges requires some more work to ensure it works correctly
* and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
*
* Multirange support annouces itself with:
* header('Accept-Ranges: bytes');
*
* Multirange content must be sent with multipart/byteranges mediatype,
* (mediatype = mimetype)
* as well as a boundry header to indicate the various chunks of data.
*/
--->
<cfheader name="Accept-Ranges" value="0-#l.length#">
<!---<cfheader name="Accept-Ranges" value="bytes"> --->
<!---
multipart/byteranges
http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 --->
<cfif structKeyExists(l.request.headers, 'Range')>
<cfset l.c_start = l.start>
<cfset l.c_end = l.end>
<!--- Extract the range string --->
<cfset l.range = ListGetAt(l.request.headers.range, 2, '=')>
<!--- Make sure the client hasn't sent us a multibyte range --->
<cflog file="rangeDownload" text="#l.range#" />
<cfif l.range contains ','>
<!--- (?) Should this be issued here, or should the first
range be used? Or should the header be ignored and
we output the whole content?
--->
<cfheader statusCode = "416" statusText = "Requested Range Not Satisfiable">
<cfheader name="Content-Range" value="bytes #l.start#-#l.end#/#l.size#">
<!--- (?) Echo some info to the client? --->
<cfabort>
</cfif>
<!--- If the range starts with an '-' we start from the beginning
If not, we forward the file pointer
And make sure to get the end byte if specified --->
<cfif Left(l.range, 1) eq '-'>
<!--- The n-number of the last bytes is requested --->
<cfset l.c_start = l.size - Mid(l.range, 2, Len(l.range))>
<cfelse>
<cfset l.rangeArray = ListToArray(l.range, '-')>
<cfset l.c_start = l.rangeArray[1]>
<cfif ArrayLen(l.rangeArray) eq 2 and val(l.rangeArray[2]) gt 0>
<cfset l.c_end = l.rangeArray[2]>
<cfelse>
<cfset l.c_end = l.size>
</cfif>
</cfif>
<!---
/* Check the range and make sure it's treated according to the specs.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
*/
// End bytes can not be larger than l.end. --->
<cfif l.c_end gt l.end>
<cfset l.c_end = l.end>
</cfif>
<!--- Validate the requested range and return an error if it's not correct. --->
<cfif l.c_start gt l.c_end || l.c_start gt (l.size - 1) || l.c_end gte l.size>
<cfheader statusCode = "416" statusText = "Requested Range Not Satisfiable">
<cfheader name="Content-Range" value="bytes #l.start#-#l.end#/#l.size#">
<!--- (?) Echo some info to the client? --->
<cfabort>
</cfif>
<cfset l.start = l.c_start>
<cfset l.end = l.c_end>
<cfset l.length = l.end - l.start + 1><!--- Calculate new content length --->
<cfscript>
context = getPageContext();
context.setFlushOutput(false);
response = context.getResponse().getResponse();
response.setContentType("video/mp4");
response.setContentLength(l.length);
</cfscript>
<cfheader statusCode = "206" statusText = "Partial Content">
</cfif>
<!--- Notify the client the byte range we'll be outputting --->
<cfheader name="Content-Range" value="bytes #l.start#-#l.end#/#l.size#">
<cfheader name="Content-Length" value="#l.length#">
<cfscript>
// Start buffered download
out = response.getOutputStream();
// write the portion requested
out.write(l.theData, javacast('int', l.start), javacast('int', l.length));
out.flush();
out.close();
</cfscript>
</cffunction>
这是我用来播放视频的JWplayer代码。
jwplayer("myElement4859").setup({
image: "path to image file",
file: "/videoreturnfile.cfm?token=4859_129_AC4E46D8-5056-A85D-6EDDE334152C27EE",
height: 360,
logo: {
file: '/images/logo_message.png',
link: 'example.com',
hide : true
},
width: 450,
type: "mp4"
});
jwplayer有什么办法可以通过它来限制我的视频应该和我的jwplayer插件一起玩吗?
或者有什么建议可以让用户下载文件变得更加复杂?
答
要阻止用户下载结果视频,而不是将视频直接嵌入到源视频中,您可以通过RTMP或HLS/MPEG-Dash以流播放视频。
这里是一个demo for webcam video recorder,还包括RTMP播放(既可以在录音机中预览,也可以根据请求提供)。
录制应用程序和播放器是基于浏览器的,您通常可以根据自己选择的语言来调整服务器端脚本。
你能看看jwplayer的请求,并确定它是否添加了任何特殊的头文件?如果是这样,你可以基于此进行过滤。您可以使用此方法支持多少个同步流。我猜不是很多。如果任何视频开始有点病毒,所有CFThreads都会忙/等待。如果头部参数丢失,您可以使用条件URL重写规则重新路由到403/404页面(并将ColdFusion从此瓶颈解决方案中取出。) –
我们使用ColdFusion(自CF3以来),并且最近从未受保护的媒体音频流切换到使用StreamGuys.com。他们允许我们通过订阅获利,保护,过期和限制为单个用户。我们生成一个加密的标记(包含用户标识,窗口和超时)并重定向到他们的媒体服务器。我们编写的基于HTML的ColdFusion应用程序比第三方开发人员创建的iOS/Android本机应用程序要好得多。 –
@JamesMoberg。我担心jwplayer不支持任何特殊的标题。使用这种方法的主要目的是在IOS上运行视频。 IOS确实需要url响应,然后开始播放视频。 –