Customize Stream Path using http instead of rtmp - http

I currently have a Red5 application that uses a Custom Stream Path similar to the example shown on
Red5's wiki.
It works great when using the following rtmp stream:
rtmp://localhost:1935/streaming/videos/myVid.mp4
I need to be able to do the same thing with a http stream.
For example:
http://localhost:8080/streaming/videos/myVid.mp4
When I change the stream url from rtmp to http the CustomFilenameGenerator class is no longer being called.
Is it possible to have a Custom Stream Path while useing http? If so, is there a configuration or something that needs added/changed to make it work?
EDIT:
Just to be clear, currently I can only stream videos to my webpage that are located in the /red5Root/webApps/myApp/videos/ directory on my server machine.
I currently can use http://my.server.ip.address/myApp/videos/videoName.mp4 inside a video tag to play a video named "videoName.mp4" located in the videos directory on my server.
I want to be able to use http://my.server.ip.address/myApp/someUniqeIdOrName and have my Red5 CustomFilenameGenerator class then return the actual path (somewhere else in the file system on my server) of the video associated with the "someUniqeIdOrName" and play the video from that location.

To play a video by plain HTTP you just need a plain web server and embed it in a VIDEO tag.
If you want to play it by HLS (HTTP Live Streaming) or MPEG Dash, you need it segmented (packetised).
Live packetisation is done by Wowza Streaming Engine and is great to deliver live streams.
For existing videos you can also use pre-segmentation that can be done with FFMPEG. You can use the free Video Share VOD turnkey site solution to easily manage videos and generate segments on your site (if you have compatible hosting with FFMPEG and necessary codecs).

I wasn't able to find a way to get this to work with my CustomFilenameGenerator class but I found a different solution that gives me the same result.
I added a redirect servlet. In my web.xml add the following:
<servlet>
<servlet-name>fileServlet</servlet-name>
<servlet-class>com.my.package.stream.app.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>fileServlet</servlet-name>
<url-pattern>/files/*</url-pattern>
</servlet-mapping>
Then I created a FileServlet class based off of the example here.
Once you get the filename from the request you can perform whatever logic based on the file name to set and return the actual location and name of the video/file you want in the response.
Example:
...
private void processRequest(HttpServletRequest request, HttpServletResponse response, boolean content) throws IOException {
// Get requested file by path info.
String requestedFile = request.getPathInfo();
// Check if file is actually supplied to the request URL.
if (requestedFile == null) {
// Do your thing if the file is not supplied to the request URL.
// Throw an exception, or send 404, or show default/warning page, or just ignore it.
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
****** Insert logic here to set basePath and requestedFile to what you need ****
// URL-decode the file name (might contain spaces and on) and prepare file object.
File file = new File(basePath, URLDecoder.decode(requestedFile, "UTF-8"));
...
With the above servlet and similar FileServlet class I am able to play videos anywhere on my server by setting src="http://[myip]:8080/[myApp]/files/[uniqeFileNameOrId]"inside a video tag on my webpage.
NOTE: If you the file you are wanting to get back from your sever is not a video a simpler example of a FileServlet class is here.

Related

Disable access to a Servlet

I'm developing a WebApp using JavaEE and I use a servlet to test some stuff.
Currently, my WebApp is set as when I go to my local url localhost:8080/myApp/test , I can run my test Servlet.
My plan is to deploy my project to a Web and I want to disable the Servlet, but not delete it. I mean, if in the future I visit my remote server via URL www.myNewWeb.com/test , I would like it throws an error od do nothing.
How could I do that?
There are many possible options here:
Option 1
Remove the mapping (annotation #WebServlet or url mapping entry in web.xml). In this case, any attempt to call this servlet will end with an error generated by the JEE container of your choice. It will try to map the servlet to URL, will obviously fail and throw an exception
The obvious drawback of this method is that you need to change the deployment configuration and if you'll want to run the same artifact in another envrironment where this servlet should work you won't be able to do so.
Option 2
Create some kind of configuration, load this configuration along with your application.
In the doGet (just for the sake of example) method do something like this:
public void doGet(request, response) {
if(config.isTestServletEnabled()) { // this is where the data gets read from configuration that I've talked about before
// do your regular processing here
}
else {
// this will happen when the servlet should not be activated
// throw an exception, return HTTP error code of your choice, etc
}
}
This way doesn't have a drawback of the first method that I've explained above, however involves some code to be written.

Spring MVC gives HTTP 406 for application/octet-stream

I am using Spring Web MVC and have written a controller that shall return binary data to a plugin in a web-page that show 3D content. This plugin uses STK files for it's models, so I have set-up my webapp to produce this kind of contents for *.stk URLs
The springDispatcherServlet is setup to handle *.stk requests in my web.xml
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>*.stk</url-pattern>
</servlet-mapping>
My controller looks like this:
#Controller
#RequestMapping(value="/3dobject", produces="application/octet-stream")
public class Object3DController {
#Autowired
private DesignerService designerService;
#RequestMapping(value="/{article}.stk", method=RequestMethod.GET, headers="Accept: application/octet-stream")
public void getObject3DForArticle(HttpServletResponse response, #PathVariable String article) throws IOException {
response.setContentType("application/octet-stream");
Object3D object = designerService.get3DModelForArticleNumber(article, LanguageCode.NORWEGIAN);
byte[] content = object.getContent();
response.setContentLength(content.length);
IOUtils.write(content, response.getOutputStream());
}
}
When I try to access the data through a browser, I get the following error:
HTTP Status 406 - The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
I have deployed my app to a tomcat server on localhost.
Any ideas of what I must do to make the browser download the binary data?
PS! I changed from *.3do (3d object) to *.stk. With 3do it worked as expected, but the plugin fails with an error (which is hard to interpret), so I have to experiment in order to verify wether or not the URL extension matters...
The RequestMapping.produces() narrows the request and therefore is
only mapped if the Accept matches one of these media types
So you need to set the corresponding Accept header in the request from the plugin. This cannot be done by simply making an HTTP GET Request by typing in a URL into a browser. One plugin I find useful for Chrome is the Advanced REST Client. There are plenty of others that offer similar functionality. Alternatively try using cURL to make the request with the correct header.

Streaming Large File Uploads in ASP.NET

I have an ASP.NET MVC application with a page that allows users to upload files. The files will be several hundred megabytes.
I am using FineUploader on the client side, which will use FileAPI/XHR if the browser supports it, otherwise will fallback to Iframe/form with enctype="multipart whatever".
So on the server side I need to evaluate Request.Files.Count > 1. If true, this is an old school upload and I save the file like Request.Files[0].InputStream.CopyTo(myFileStream) otherwise I do Request.InputStreawm.CopyTo(myFileStream).
Here's some of the actual code I've written that does this stuff: https://github.com/ronnieoverby/file-uploader/blob/master/server/ASP.NET%20MVC%20C%23/FineUpload.cs
This all works fine, but in my testing I've noticed that neither an ASP.NET MVC controller action nor an HttpHandler will begin processing until the entire file is uploaded, which is bad if the file very large because that means it's occupying a lot of the web server's RAM.
I found this: Streaming large file uploads to ASP.NET MVC which sounds promising, but I really don't have an idea of where the code resides in his application.
So, the question is: how to stream uploaded files to disk while the upload is still taking place in ASP.NET?
Update
I just saw a key detail that didn't sink in before. From the HttpPostedFile documentation:
By default, all requests, including form fields and uploaded files,
larger than 256 KB are buffered to disk, rather than held in server
memory.
Ok, that addresses the concern that the web server's RAM utilization could spike during a large upload. But, there's still a problem: After the file is completely transferred to the web server, the server has to spend time moving it to it's final destination. If the file system operation is a copy (guaranteed if the destination is on another physical disk), then the response is delayed unnecessarily.
Honestly, I could probably live with this by increasing response timeout for the upload handler/action. But, it would be nice to stream the bytes directly to their destination.
You can handle uploads in a completely customized way without buffering using
HttpRequest.GetBufferlessInputStream method. Basically you are getting access to the raw incoming data and free to do whatever you want with it.
I've just created small sample which saves raw request content to a file:
Create handler:
public class UploadHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
using (var stream = context.Request.GetBufferlessInputStream())
using (var fileStream = File.Create("c:\\tempfile.txt"))
{
stream.CopyTo(fileStream);
}
}
public bool IsReusable { get { return true; } }
}
Register in Web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<handlers>
<add name="UploadHandler" verb="POST"
path="/upload"
type="UploadHandler"
resourceType="Unspecified"/>
</handlers>
</system.webServer>
Create a page with a form:
<form action="/upload" method="post" enctype='multipart/form-data'>
<input type="file" name="aa" id="aa"/>
<input type="submit"/>
</form>
If the uploading and streaming is using up valuable server resources then you might wanna take a look at hosting your media files on a cloud of some sort. It's possible with ASP.NET to use a Rackspace, Amazon Cloud API have your users upload the files directly to a CDN network and then serve the content that way, I know this isn't answering your question but many people will or already have and thought I'd get my 2 cents in. Many people still not opting to use the cloud amazes me! once you go CDN you never go back. Furthermore with most CDN's you will also be given a streaming URL for your upload container where it supports lots of different movie types, and its lighting fast, not only for your users to upload too but also your never have slow speeds on your website as a result.

HttpHandler to download txt files (ASP.NET)?

Hey, I created a HttpHandler for downloading files from the server. It seems it is not handling anything...I put a breakpoint in the ProcessRequest, it never goes there.
public class DownloadHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//download stuff and break point
}
}
It never stops there, as mentioned. I also registered it in the web.config.
<add verb="*" path="????" type="DownloadHandler" />
I am not sure about the path part of that entry. What do I have to enter there? I am downloading txt files, but the URL does not contain the filename, I somehow have to pass it to the handler. How would I do this? Session maybe?
Thanks
Have you read How to register Http Handlers? Are you using IIS 6 or 7?
The path part should contain a (partial) url, so if in your case you are using a static url without the filenames, you should put that there. You can end the url in the name of a non-existent resource and map that to path
e.g. the url is http://myserver.com/pages/downloadfiles
and the path="downloadfiles"
If you do POST, you can put the filename in a hidden field, and extract it in the handler. If you're using GET, I'm not sure, either cross-post the viewstate or put the filename in the session like you said.
Any reason why you can't put the filename in the url?
The path for a handler needs to be the path you are trying to handle - bit of a tautology I know but it's as simple as that. Whatever path on your site (real or much more likely virtual) you want to be handled by this handler.
Now unless the kind of file at the end of that path is normally handled by ASP.NET (e.g. .aspx, .asmx but not a .txt) ASP will never see the request in order for it to go through it's pipeline and end up at your handler. In that case you have to bind the extension type in IIS to ASP.NET.
As far as identifying what file the handler is supposed to respond with you could achieve this any number of ways - I would strongly recommend avoiding session or cookies or anything temporal and implicit. I would instead suggest using the querystring or form values, basically anything which will show up as a request header.
Fianlly, I have to ask why you're using a handler for this at all - .txt will serve just fine normally so what additional feature are you trying to implement here? There might well be a better way.

Posting base64 encoded files to an asp.net 1.1 page

We are making an automated patching application and would like to post files on production server through asp.net page (or maybe a web service), since we can only access production server via http. The page should accept files and store them to appropriate location. The path to files will be declared in external XML file.
So, is it possible posting a base64 encoded files within body tag and HOW? maybe even any better approach?
If you plan to use Base64 encoding.
Take a look at
System.Convert.ToBase64String()
System.Convert.FromBase64String()
System.Convert.ToBase64CharArray()
System.Convert.FromBase64CharArray()
See Using XML CDATA nodes to send files via a Web Service
why not create a webservice which accepts an object like:
class postfile
{
public byte[] fileByte;
public string fileName;
}
Then add a web reference in your client app.
.net will serialize the object for you.
You will need to secure this using wse security and might require the service use impersonation to write the file on the server.

Resources