I want to download and play m3u8 file which is on server machine. I am using following code to read and send m3u8 file to web server.
Browser is displaying contents of file instead of downloading it.
So please let me know that, how to download it.
if ((exportHandle = fopen(v3FileName, "a+")) != NULL) {
long end = 0, start = 0, pos = 0;
char* m3u8FileDataBuff = NULL;
fseek(exportHandle, 0, SEEK_END);
end = ftell(exportHandle);
fseek(exportHandle, 0, SEEK_SET);
start = ftell(exportHandle);
pos = end - start;
m3u8FileDataBuff = (char *) malloc(pos);
end = 0;
start = 0;
fread(m3u8FileDataBuff, 1, pos, exportHandle);
pClienCommunication->writeBuffer(m3u8FileDataBuff, pos);
free(m3u8FileDataBuff);
fclose(exportHandle);
}
Client's web browser is displaying the content, because the MIME type of the response is either nil, or something like "text/plain". Set up the http response header properly to indicate mime type of m3u8 file (application/x-mpegURL or vnd.apple.mpegURL).
The piece of code you provided does not seem to set anything around response header, just content.
Check available API of pClienCommunication->, or place where that originates, what are your options to adjust response header.
Or maybe it's possible to work-around this also by some rule set up in the web server serving the response, to set the MIME type for certain URLs, or based on the response content (but applying such rules on web server level is usually more costly then adjusting the response while being created in the C++ part).
And why is this tagged C++, when the code itself is C-like with all the problems of it. In modern C++ you never do things like "fclose(..)", because that is done in the destructor of the file wrapper class, so you don't risk the fclose will be skipped in case of some exception raised in fread, etc.
So in modern C++ these things should look somewhat like this:
{
SomeFileClass exportFile(v3FileName, "a+");
if (exportFile.isOK()) {
SomeFileContentBuffer data = exportFile.read();
pClienCommunication->writeBuffer(data.asCharPtr(), data.size());
}
}
So you can't forget to release any file handle, or buffer memory (as the destructors of particular helper classes will handle that).
Related
Can I perform something like this?
Situation
I want to check the URL. if URL equal to http://sample.com, do this, otherwise, do that.
What I did:
In Web.config -
<add key="ServerURLCloud" value="sample.com" />
In C# -
public static string GetURL()
{
string[] url = ConfigurationManager.AppSettings["ServerURLCloud"];
return url;
}
In Javascript -
if(varURL.indexOf('#ClassName.GetURL()') > 0){
urlToCall = 'sub.sample.com';
}else{
urlToCall = 'sub.not-sample.com';
}
$ajax(
url = urlToCall,
data = .........
....
)
I tested it, it is working very well. But, I want to know, will it be any problem if:
Internet connection slow
EDITED:
My Question
Is this practice (get Server side information at JavaScript) is good? Or bad?
i believe this code sample can be altered slightly to make it a little easier to maintain.
You could create a variable in your layout which could contain ConfigurationManager.AppSettings["ServerURLCloud"]
var siteSettings = {};
siteSettings.serverUrlCloud = '#ConfigurationManager.AppSettings["ServerURLCloud"]';
siteSettings.subSampleUrl = 'url';
siteSettings.subNotSampleUrl = '';
This site settings can hold anything useful as well (like base url etc)...
Also, try not to use magic strings in your code... instead, prefer to create variables/consts etc which hold these.
These changes wont impact the speed of your application but they will make it slightly easier to manage.
Also, the speed of the response from your ajax request is completely down to the executed code within that request, the length of the response and the internet connection speed... if the code is complex and doing a lot then it will naturally take longer. If the response is big, it will take longer to download. If the internet connection is slow, it will take longer to send the request and download the response.
Hope this helps
I'm developing some webGL project in Unity that has to load some external images from a directory, it runs all fine in the editor, however when I build it, it throws a Directory Not Found exception in web console. I am putting the images in Assets/StreamingAssets folder, that will become StreamingAssets folder in the built project (at root, same as index.html). Images are located there, yet browser still complains about not being able to find that directory. (I'm opening it on my own computer, no running web server)
I guess I'm missing something very obvious, but it seems like I could use some help, I've just started learning unity a week ago, and I'm not that great with C# or JavaScript (I'm trying to get better...) Is this somehow related to some javascript security issues?
Could someone please point me in the right direction, how I should be reading images(no writing need to be done) in Unity WebGL?
string appPath = Application.dataPath;
string[] filePaths = Directory.GetFiles(appPath, "*.jpg");
According to unity3d.com in webGL builds everything except threading and reflection is supported, so IO should be working - or so I thought:S
I was working around a bit and now I'm trying to load a text file containing the paths of the images (separated by ';'):
TextAsset ta = Resources.Load<TextAsset>("texManifest");
string[] lines = ta.text.Split(';');
Then I convert all lines to proper path, and add them to a list:
string temp = Application.streamingAssetsPath + "/textures/" + s;
filePaths.Add(temp);
Debug.Log tells me it looks like this:
file://////Downloads/FurnitureDresser/build/StreamingAssets/textures/79.jpg
So that seems to be allright except for all those slashes (That looks a bit odd to me)
And finally create the texture:
WWW www = new WWW("file://" + filePaths[i]);
yield return www;
Texture2D new_texture = new Texture2D(120, 80);
www.LoadImageIntoTexture(new_texture);
And around this last part (unsure: webgl projects does not seem easily debuggable) it tells me: NS_ERROR_DOM_BAD_URI: Access to restricted URI denied
Can someone please enlighten me what is happening? And most of all, what would be proper to solution to create a directory from where I can load images during runtime?
I realise this question is now a couple of years old, but, since this still appears to be commonly asked question, here is one solution (sorry, the code is C# but I am guessing the javascript implementation is similar). Basically you need to use UnityWebRequest and Coroutines to access a file from the StreamingAssets folder.
1) Create a new Loading scene (which does nothing but query the files; you could have it display some status text or a progress bar to let the user knows what is happening).
2) Add a script called Loader to the Main Camera in the Loading scene.
3) In the Loader script, add a variable to indicate whether the asset has been read successfully:
private bool isAssetRead;
4) In the Start() method of the Loading script:
void Start ()
{
// if webGL, this will be something like "http://..."
string assetPath = Application.streamingAssetsPath;
bool isWebGl = assetPath.Contains("://") ||
assetPath.Contains(":///");
try
{
if (isWebGl)
{
StartCoroutine(
SendRequest(
Path.Combine(
assetPath, "myAsset")));
}
else // desktop app
{
// do whatever you need is app is not WebGL
}
}
catch
{
// handle failure
}
}
5) In the Update() method of the Loading script:
void Update ()
{
// check to see if asset has been successfully read yet
if (isAssetRead)
{
// once asset is successfully read,
// load the next screen (e.g. main menu or gameplay)
SceneManager.LoadScene("NextScene");
}
// need to consider what happens if
// asset fails to be read for some reason
}
6) In the SendRequest() method of the Loading script:
private IEnumerator SendRequest(string url)
{
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
// handle failure
}
else
{
try
{
// entire file is returned via downloadHandler
//string fileContents = request.downloadHandler.text;
// or
//byte[] fileContents = request.downloadHandler.data;
// do whatever you need to do with the file contents
if (loadAsset(fileContents))
isAssetRead = true;
}
catch (Exception x)
{
// handle failure
}
}
}
}
Put your image in the Resources folder and use Resources.Load to open the file and use it.
For example:
Texture2D texture = Resources.Load("images/Texture") as Texture2D;
if (texture != null)
{
GetComponent<Renderer>().material.mainTexture = texture;
}
The directory listing and file APIs are not available in webgl builds.
Basically no low level IO operations are supported.
I've a DataSnap server method
function TServerMethods.GetFile(filename): TStream
returning a file.
In my test case the file is a simple .PDF.
I'm sure this function works fine, as I'm able to open files on ObjectiveC client side app's where I've used my own http call to the DataSnap method (no Delphi proxy).
The stream is read from ASIHttpRequest object and saved as local file, then loaded and regulary shown in standard pdf reader.
I do not kown how exactly ASIHttpRequest manages the returned data.
But on JavaScript client side where I use standard
stream = ServerMethods().GetFile('test.pdf')
JavaScript function, as provided from DataSnap proxy itself, I do not figure out how to show the .pdf data to the user.
Using
window.open().document.write(stream);
a new browser window opens with textual raw data ( %PDF-1.5 %âãÏÓ 1 0 obj << /Type /Catalog /Pages 2 0 R …..)
With
window.open("data:application/pdf;base64," +stream);
I get an empty new browser page.
With
window.open("data:application/pdf," +stream);
or
document.location = 'data:application/pdf,'+encodeURIComponent(serverMethods().GetFile('test'));
I get an new browser page with pdf empry reader and alert “This PDF document could not be displayed correctly”
Nothing changes adding:
GetInvocationMetadata().ResponseContentType := 'application/pdf';
into the DataSnap function.
I've no other ideas...
EDIT
The task is for a general file download, not only PDF. PDF is a test only. GetFile have to manage .pdf, .xlsx, .docx, .png, .eml, etc...
Your server side code works as expected once you set the ResponseContentType. You can test this by calling the method directly from a browser. Change the class name to match the one you're using:
http://localhost:8080/datasnap/rest/TServerMethods1/GetFile/test.pdf
I'm sure there's a way to display the stream properly on the browser side, but I'm not sure what that is. Unless you're doing something special with the stream, I'd recommend getting the document directly or using a web action and getting out of the browser's way. Basically what mjn suggested.
I can think of a couple of solutions.
1) A quick way would be to allow access to the documents directly.
In the WebFileDispatcher, add a WebFileExtension. Select .pdf and it will fill in the mime type for you. Assuming your pdf documents are in the "docs" folder, the url might look like this:
http://localhost:8080/docs/test.pdf
2) I would probably add an action on the web module. It's a little more involved, but it also gives me more control.
Using this url:
http://localhost:8080/getfile?filename=test.pdf
And code like this in the web action handler (no checking or error handling). The Content-Disposition header suggests a file name for the downloaded file:
procedure TWebModule1.WebModule1GetFileActionAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
lStream: TMemoryStream;
lFilename: string;
begin
lFilename := Request.QueryFields.Values['filename'];
lStream := TMemoryStream.Create;
lStream.LoadFromFile('.\Docs\' + lFilename);
lStream.Position := 0;
Response.ContentStream := lStream;
Response.ContentType := 'application/pdf';
Response.SetCustomHeader('Content-Disposition',
Format('attachment; filename="%s"', [lFilename]));
end;
With relation to Exception "The disk is full " is thrown when trying to store data in usedata object in IE7+ which has been left unanswered:
I am heavily browsing a government website created with Oracle ADF using WatiN.
The website is located in a WPF window --> WindowsFormsHost --> WebBrowser control.
The website makes heavy use of this: http://msdn.microsoft.com/en-us/library/ie/ms531424(v=vs.85).aspx, via the save and load methods.
After 2-3 minutes of browsing, I get the following javascript error during one of the "save" calls:
The disk is full, character #, line ####.
When I get this error, the WebBrowser control is rendered completely useless (no further javascript commands can be executed) and my app must be restarted.
I have tried to clear browser cache, change it's location, clear localStorage, everything to no avail.
The PC that reproduces the error has IE10 installed, but via the registry I force IE8 / IE9 mode in the webbrowser control.
Is there any way to get around this problem?
Information on this is very scarce, so any help will be greatly appreciated.
I'm on linux, so no way to test this now, but the files in question are not stored in browser cache, but in
Note: As of IE 10 this no longer holds water. Ref. edit 2 below.
W7+: %HOMEPATH%\AppData\Roaming\Microsoft\Internet Explorer\UserData
# c:\users\*user-name*\...
XP : %HOMEPATH%\Application Data\Microsoft\Internet Explorer\UserData
# c:\Documents and Settings\*user-name*\...
Or, I guess, this one also work (as a short-cut), :
%APPDATA%\Roaming\Microsoft\Internet Explorer\UserData
Modify or delete the files there.
Note that the files are tagged as protected operating system files, so to view in Explorer you have to change view to include these. If you use cmd, as in Command Prompt you have to include the /a flag as in:
dir /a
Edit 1:
Note, that index.dat is the one holding information about allocated size etc. so it won't (probably) help to only delete/move the xml files.
Edit 2:
OK. Had a look at this in Windows 7 running IE 10.
In IE 7 (on XP) the above mentioned path have an index.dat file that gets updated on save by userData. The file holds various information such as size of the index file, number of sub folders, size of all files. Then an entry for each file with a number identifying folder, url where it was saved from, name of xml file, dates etc. Wrote a simple VBScript parser for this, but as IE 10 does not use the index.dat file it is a waste.
Under IE 10 there is no longer various index.dat files but a central database file in:
%APPDATA%\Local\Microsoft\Windows\WebCache\
On my system the database file is named WebCacheV01.dat, the V part seems to differ between systems and is perhaps an in-house version number rather then a file type version.
The files are tightly locked, and as such, if one want to poke at them one solution is to make a shadow copy by using tools such as vscsc, Shadowcopy etc.
Anyhow, hacking WebCacheVxx.dat would need a lot more work, so no attempts on that on my part (for now at least).
But, register that the file gets an entry with path to the old location – so e.g. on write of someElement.save("someStorageName");, WebCacheVxx.dat gets an entry like:
...\AppData\Roaming\Microsoft\Internet Explorer\UserData\DDFFGGHH\someStorageName[1].xml
and a corresponding file is created in the above path.
The local container.dat, however, is not updated.
userData
As for the issue at hand, clearing localStorage will not help, as userData is not part of that API.
Can not find a good example on how to clear userData. Though, one way is to use the console.
Example from testing on this page:
Save some text.
Hit F12 and enter the following to clear the data:
/* ud as an acronym for userData */
var i, at,
ud_name = "oXMLBranch",
ud_id = "oPersistText",
ud = document.getElementById(ud_id);
/* To modify the storage one have to ensure it is loaded. */
ud.load(ud_name);
/* After load, ud should have a xmlDocument where first child should hold
* the attributes for the storage. Attributes as in named entries.
*
* Example: ud.setAttribute("someText", "Some text");
* ud.save(ud_name);
*
* XML-document now has attribute "someText" with value "Some text".
*/
at = ud.xmlDocument.firstChild.attributes;
/* Loop attributes and remove each one from userData. */
for (i = 0; i < at.length; ++i)
ud.removeAttribute(at[i].nodeName);
/* Finally update the file by saving the storage. */
ud.save(ud_name);
Or as a one-liner:
var ud_name = "oXMLBranch", ud_id = "oPersistText", i, at, ud = document.getElementById(ud_id); ud.load(ud_name); at = ud.xmlDocument.firstChild.attributes; for (i = 0; i < at.length; ++i) ud.removeAttribute(at[i].nodeName); ud.save(ud_name);
Eliminating one restriction
There are some issues with this. We can eliminate at least one, by ignoring the ud_id and instead create a new DOM object:
var i, at,
ud_name = "oXMLBranch",
ud = document.createElement('INPUT');
/* Needed to extend properties of input to include userData to userdata. */
ud.style.behavior = 'url(#default#userdata)';
/* Needed to not get access denied. */
document.body.appendChild(ud);
ud.load(ud_name);
at = ud.xmlDocument.firstChild.attributes;
for (i = 0; i < at.length; ++i)
ud.removeAttribute(at[i].nodeName);
/* Save, or nothing is changed on disk. */
ud.save(ud_name);
/* Clean up the DOM tree */
ud.parentNode.removeChild(ud);
So by this one should be able to clear userData by knowing name of the storage, which should be same as the file name (excluding [1].xml) or by looking at the page source.
More issues
Testing on the page mentioned above I reach a disk is full limit at 65,506 bytes.
Your problem is likely not that the disk is full, but that a write attempt is done where input data is above limit. You could try to clear the data as mentioned above and see if it continues, else you would need to clear the data about to be written.
Then again this would most likely break the application in question.
In other words, error text should have been something like:
Write of NNN bytes is above limit of NNN and not disk is full.
Tested by attaching to window onerror but unfortunately source of error was not found:
var x1, x2, x3, x4 ;
window.onerror = function () {
x1 = window.event;
x2 = x1.fromElement; // Yield null
x3 = x1.srcElement; // Yield null
x4 = x1.type;
};
End note
Unless the clear userData method solves the issue, I do not know where to go next. Have not found any option to increase the limit by registry or other means.
But perhaps it get you a little further.
There might be someone over at Super User that is able to help.
I am trying to capture a still frame from an (any) external swf file, by using my own flash movie as a proxy to load it and hand information regarding the Stage onto javascript. I want to keep it as wide compatible as possible, so I went with AS2 / Flash 8 for now.
The script works fine in the Flash debugger, i.e. the
trace(flash2canvasScreenshot.getPixel(w, h).toString(16));
returns the correct pixel color, where as:
ExternalInterface.call("sendToJS",flash2canvasScreenshot.getPixel(w, h).toString(16));
in the published movie doesn't.
This method can obviously be quite slow for large flash (dimension wise) movies, as it iterates every single pixel. If someone has any better methods in mind, feel free to share, but as said, the problem I am facing is that I am getting differentiating results in debugging and publishing, with the pixel information not getting fetched when published.
import flash.display.BitmapData;
import flash.external.*;
var myLoader:MovieClipLoader = new MovieClipLoader();
var mclListener:Object = new Object();
mclListener.onLoadInit = function(target_mc:MovieClip)
{
var stageW = Stage.width;
var flash2canvasScreenshot:BitmapData = new BitmapData(stageW, Stage.height, false, 0x00000000);
var pixels:Array = new Array();
flash2canvasScreenshot.draw(element);
for (w = 0; w <= stageW; w++)
{
trace(flash2canvasScreenshot.getPixel(w, h).toString(16)); // this gives correct color value for the pixels in the debugger
ExternalInterface.call("sendToJS",flash2canvasScreenshot.getPixel(w, h).toString(16)); // this just returns the bitmap default color, 0 in this case.
/*
for (h = 0; h <= Stage.height; h++)
{
var pixel = flash2canvasScreenshot.getPixel(w, h).toString(16);
pixels.push(pixel);
}
*/
}
//ExternalInterface.call("sendToJS",pixels.toString());*/
};
myLoader.addListener(mclListener);
myLoader.loadClip("http://i.cdn.turner.com/cnn/cnnintl_adspaces/2.0/creatives/2010/6/9/21017300x250-03.swf", 0);
//myLoader.loadClip("https://s.ytimg.com/yt/swfbin/watch_as3-vflJjAza6.swf", 0);
//myLoader.loadClip(_level0.flash2canvasurl, _root.mc);
There are few problems with the snippet you posted:
like the one Joey mentioned, but the one that stands out from my
point of view is the element variable which isn't defined
anywhere, so that either is a type o, or you're trying to draw an
undefined object.
You're drawing as soon as the load is finished, but the animation you're loading might start slightly later. Maybe take the snapshot a bit after the load is complete.
Haven't touched as2 for some time and don't remember how security issue are handled, but if you're swf is loading another swf from a different domain, then the domain hosting the swf you're loading should also have a crossdomain.xml policy file allowing you to access the content of the loaded swf. If you simply load and display a swf from another domain, that's fine. However, if you're trying to draw the swf using BitmapData, you're actually attempting to access pixel data from the content of that swf, therefore you would need permissions. If you have no control over the crossdomain policy file, you might need to use a server side script to copy/proxy the file over to a domain that can grant your loaded swf access.
Here's a simplified version of your snippet that works (sans the external interface/pixel values part):
var myLoader:MovieClipLoader = new MovieClipLoader();
var mclListener:Object = new Object();
mclListener.onLoadInit = function(target_mc:MovieClip)
{
var pixels:Array = new Array();
setTimeout(takeSnapshot,2000,target_mc);
}
myLoader.addListener(mclListener);
myLoader.loadClip("http://www.bbc.co.uk/science/humanbody/sleep/sheep/reaction_version5.swf",1);
//myLoader.loadClip("http://i.cdn.turner.com/cnn/cnnintl_adspaces/2.0/creatives/2010/6/9/21017300x250-03.swf", 1);
//myLoader.loadClip("https://s.ytimg.com/yt/swfbin/watch_as3-vflJjAza6.swf", 0);
function takeSnapshot(target:MovieClip):Void {
var flash2canvasScreenshot:BitmapData = new BitmapData(150, 150, false, 0x00000000);//tiny sample
flash2canvasScreenshot.draw(target);
_level1._alpha = 20;//fade the loaded content
_level0.attachBitmap(flash2canvasScreenshot,0);//show the snapshop. sorry about using _root
}
Here's a quick zoomed preview of the 150x150 snap:
Here's an as3 snippet to illustrate the security sandbox handling issue:
var swf:Loader = new Loader();
swf.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderComplete);
swf.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,loaderSecurityError);
swf.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,loaderIOError);
swf.load(new URLRequest("http://i.cdn.turner.com/cnn/cnnintl_adspaces/2.0/creatives/2010/6/9/21017300x250-03.swf"),new LoaderContext(true));
function loaderComplete(event:Event):void{
setTimeout(takeSWFSnapshot,2000);
}
function loaderSecurityError(event:SecurityErrorEvent):void {
trace('caught security error',event.errorID,event.text);
}
function loaderIOError(event:IOErrorEvent):void{
trace('caught I/O error',event.errorID,event.text,'\tattempting to load\t',swf.contentLoaderInfo.url);
}
function takeSWFSnapshot():void{
var clone:BitmapData = new BitmapData(swf.content.width,swf.content.height,false,0);
try{
clone.draw(swf.content);
}catch(e:SecurityError){
trace(e.name,e.message,e.getStackTrace());
}
addChild(new Bitmap(clone));
}
HTH
My approach to this would be:
-Use AS3 for the reason lukevanin commented:
Just remember that AS3 can load an AS2 SWF, but an AS2 SWF cannot load
an AS3 SWF, so you actually achieve greater compatibility (with your
content) if you publish AS3
-Use a proxy file to fetch the swf file to get around sandbox violation issues (although if the swf loads external resources and uses relative paths it might get a bit more complex)
-Take a snapshot of the frame ( see George Profenza's solution )
-Encode the image using base64 and send that** to a JS method, and then decode to get the image.
** I'm pretty sure there are no size limitations...