accessing local files?
Monkey Targets Forums/HTML5/accessing local files?
| ||
don't suppose anyone has any code for reading text files off of the local harddrive? |
| ||
That won't work in HTML5 because of this sandbox protection. HTML5 apps are simply not allowed to access anything outside as far as I know. |
| ||
It can be done, but it has to happen under user control (they have to click a button and select the file) and then you might have to upload it to the same server as your app before you can access it (from there). I can't remember the exact details. More here: http://www.w3schools.com/jsref/dom_obj_fileupload.asp Also, search for FileReader. |
| ||
That won't work in HTML5 because of this sandbox protection. HTML5 apps are simply not allowed to access anything outside as far as I know. I'm reading text files okally dokally.... in HTML5, looking for an example for you now... You don't need to upload the files to a server, they can be accessed from the user's device within the following example. As Beaker says, you need to select a 'browse' button first.... in my example below anyhow. [EDIT] There might be a bit much to chew on, but this code will load three separate 'text' files and do a bit of data parsing: (incidentally, I was trying to load an image of the user's choice using the following code. After a bit of digging it appears as though MonkeyX creates a small database of images at compile time - I haven't been able to find a work around to achieve my goal of loading a users image after compiling and have given up on that for now.... hope the following helps you out anyways ;) Strict ' Preprocessor related: #MOJO_AUTO_SUSPEND_ENABLED = False ' Imports: Import mojo Import brl.databuffer Import brl.datastream ' Check if we're using HTML5: #If TARGET = "html5" Import dom Import "native/file_to_databuffer.js" ' External bindings (JavaScript): Extern ' Functions: ' File-to-DataBuffer: Function LoadFile:DataBuffer(F:File, B_Out:DataBuffer)="loadFile" ' DOM: Function log:Void(e:Event) = "window.console.log" Function log:Void(f:FileList) = "window.console.log" Function log:Void(f:File) = "window.console.log" 'Function log:Void(o:Object) = "window.console.log" ' Classes: Class File ' Fields: Field lastModified:Int Field lastModifiedDate:String Field name:String Field size:Int Field fileName:String Field fileSize:Int Field type:String End Class FileList Extends DOMObject ' Fields: Field length:Int ' Methods: Method item:File(index:Int) End Class HTMLFileInputElement Extends HTMLInputElement = "HTMLInputElement" ' Fields: Field files:FileList End Public Class AllDataHolder ' Globals Field AllDataList:String[] End ' Classes: Class EventRepeater Extends EventListener ' Constructor(s): Method New(Callback:EventHandler) Self.Callback = Callback End ' Methods: Method handleEvent:Int(event:Event) Return Callback.HandleEvent(event) End ' Fields: Field Callback:EventHandler End ' Functions: Function AddFileRequester:HTMLFileInputElement(listener:EventListener, node:dom.Node) Local input:= HTMLFileInputElement(document.createElement("input")) ' HTMLInputElement input.type = "file" input.addEventListener("change", listener) node.appendChild(input) Return input End Function AddButton:HTMLInputElement(name:String, listener:EventListener, node:dom.Node) Local button:= document.createElement("input") button.setAttribute("type", "button") button.setAttribute("name", name) button.setAttribute("value", name) button.addEventListener("click", listener) node.appendChild(button) Return HTMLInputElement(button) End #Else #Error "Please build this application with the HTML5 target." #End ' Interfaces: Interface EventHandler ' Methods: Method HandleEvent:Int(event:Event) End ' Classes: Class FileApp Extends App Implements EventHandler ' Constant variable(s): Const FILES_NEEDED:= 3 ' Methods: Method OnCreate:Int() SetUpdateRate(30) ' 0 ' 60 Self.running = False Self.filesQueued = 0 ' This is a dummy object used to get around the limitations of DOM: Self.repeater = New EventRepeater(Self) Self.bodyNode = dom.Node(Element(document.getElementsByTagName("body").item(0)).getElementsByTagName("div").item(0)) Self.fileButtons = New HTMLFileInputElement[FILES_NEEDED] Self.files = New DataBuffer[FILES_NEEDED] ' Self.fileButtons.Length For Local I:= 0 Until fileButtons.Length ' FILES_NEEDED Self.fileButtons[I] = AddFileRequester(repeater, bodyNode) Next #If CONFIG = "debug" MakeRunButton() #End Return 0 End '============ Start of the Event handler - how do I invoke a file requester associated '============ with one of 'my buttons' (as opposed to the procedurally generated 'Browse' '============ button ........... - Specifically trying to associate a file requester '============ with the 'LoadMyMap' button. Method HandleEvent:Int(event:Event) Select event.type Case "change" Local fileButton:= GetFileButton(event.target) If (fileButton <> Null And files.Length > filesQueued) Then Local f:File = fileButton.files.item(0) Print("New file: ~q" + f.name + "~q - " + f.size + " bytes") files[filesQueued] = LoadFile(f, New DataBuffer()) filesQueued += 1 Endif Case "click" If (event.target = runButton) Then 'Local runButton:= Self.runButton OnRunButtonPressed() Else If (event.target = LoadMyMapButton) OnLoadMyMapButtonPressed() Else If (event.target = scaleUpButton) OnScaleUpButtonPressed() Else If (event.target = scaleDownButton) OnScaleDownButtonPressed() Endif End Select Return 1 End Method OnFilesLoaded:Void() If (runButton <> Null) Then Return Endif 'Calls to generate required buttons 'Note: Require Bool to do this ONCE If generateButtons = 0 generateButtons = 1 MakeLoadMyMapButton() MakeScaleUpButton() MakeScaleDownButton() Endif End '===============Load My Image in button Method MakeLoadMyMapButton:Void() LoadMyMapButton = AddButton("Load My Map", repeater, bodyNode) Return End Method OnLoadMyMapButtonPressed:Void() Print("Map Picker Button Pressed: TO DO, suss how to open a file browser to pick image from users device....") '------------- Attempt to open a file browser 'Local fileButton:= GetFileButton(event.target) 'If (fileButton <> Null And files.Length > filesQueued) Then ' Local f:File = fileButton.files.item(0) ' Print("New file: ~q" + f.name + "~q - " + f.size + " bytes") ' files[filesQueued] = LoadFile(f, New DataBuffer()) ' filesQueued += 1 'Endif '===============map out button Return End Method OnScaleUpButtonPressed:Void() If ScaleFloat <= 20 Then ScaleFloat = ScaleFloat+0.2 Print("Scale Up Button Pressed: ")+ScaleFloat Return End Method OnScaleDownButtonPressed:Void() If ScaleFloat >= 0.2 Then ScaleFloat = ScaleFloat-0.2 If ScaleFloat <= 0.2 Then ScaleFloat = ScaleFloat-0.05 Print("Scale Down Button Pressed: ")+ScaleFloat Return End Method MakeScaleUpButton:Void() 'If (scaleUpButton <> Null) Then ' Return 'Endif scaleUpButton = AddButton("Zoom Image In", repeater, bodyNode) Return End Method MakeScaleDownButton:Void() 'If (scaleDownButton <> Null) Then ' Return 'Endif scaleDownButton = AddButton("Zoom Image Out", repeater, bodyNode) Return End Method OnRunButtonPressed:Void() If (running Or Not AllFilesLoaded) Then Return Endif running = True Print("Starting the application properly.") Return End Method MakeRunButton:Void() If (runButton <> Null) Then Return Endif runButton = AddButton("Show the data racing", repeater, bodyNode) Return End Method GetFileButton:HTMLFileInputElement(target:EventTarget) For Local I:= 0 Until fileButtons.Length If (fileButtons[I] = target) Then ' EventTarget(...) Return fileButtons[I] Endif Next Return Null End Method OnUpdate:Int() If (Not running) Then If (AllFilesLoaded) Then OnFilesLoaded() 'calling the readOnce within OnFilesLoaded..... Endif Return 0 Endif If (MouseHit(MOUSE_LEFT)) Then 'If (Not readOnce) 'ReadLoadedFiles() 'If readOnce=True 'Print "returned from ReadLoaded Files, readOnce is: TRUE" 'Endif 'If (Not running) 'Print("Parsing Files Now.... Please Wait.") 'ParseLoadedFiles() 'DebugParsedFiles() 'Else ' Print ("Already parsed loaded files...") ' Print ("So what is calling the parser again....") 'Endif 'Endif DrawText("Detected left mouse hit",8.0,32.0) Endif If (running And readOnce) DisplayParsedFiles() 'Print "Called DisplayParsedFiles()..." Else If running Print ("DEBUG: running is: TRUE") Else Print("DEBUG: runing is FALSE") Endif If readOnce Print ("DEBUG: readonce is TRUE") Else Print ("DEBUG: readonce is FALSE") Endif Endif Return 0 End Method OnRender:Int() Cls() '########################### 'this is the issue I have with footprints - the rendering of the square has to happen here!!!! 'no biggy really..... '2 Nov 16: sorting footprints to go in correct cardinal directions '########################## Local i:Int = 1 Local xarray:Int[5000] Local yarray:Int[5000] Local xct:Int = 1 Local yct:Int = 1 Local plotredfoots:Int = 1 Local howlong:Int = 1 If (Not running) Then If (AllFilesLoaded) Then DrawText("All files have been loaded.", 8.0, 8.0) DrawText("Now to attempt to load and display an image for subsequent manipulation", 8.0, 19.0) Endif DrawImage map,xmap,ymap,MapRotate,MapZoom,MapZoom Return 0 Else ' This basically never happens. DrawText("Waiting for TCX files to be uploaded / imported; " + FilesCompleted + " completed.", 8.0, 8.0) Endif Return 0 End Method ReadLoadedFiles:Void() For Local I:= 0 Until files.Length Local buffer:= files[I] Local inputStream:= New DataStream(buffer) Print("") Print("Parsing file #" + (I+1) + ":") Print("Last file length was:" +(lastNumberOfLines)) Print("") While (Not inputStream.Eof()) ' Read the current line. Local line:= inputStream.ReadLine() 'Print("Line: " + line) 'Print(" 1_3_5_7_9_1_3_5_9_1_3_5_9_1_3_5_9") 'Copy line into an array for parsing AllDataList = AllDataList.Resize(AllDataList.Length() + 1) AllDataList[AllDataList.Length() - 1] = line numberOfLines = numberOfLines + 1 'required to store where file 2 and file 3 start within the AllDataList buffer lastNumberOfLines = numberOfLines If I = 0 fileOneEnd = numberOfLines Endif If I = 1 fileTwoEnd = numberOfLines Endif If I = 2 fileThreeEnd = numberOfLines endif Wend inputStream.Close() Print "fileEndCounts -----------" Print "fileOneEnd = " + fileOneEnd Print "fileTwoEnd = " + fileTwoEnd Print "fileThreeEnd = " + fileThreeEnd readOnce = True Next Print(" ") Print("========== End of parsing files===========") Print(" Number of lines read: "+numberOfLines) Print(" ") If readOnce=True Print ("In ReadLoadedFiles: readOnce is TRUE") Endif Return End Method ParseLoadedFiles:Void() End Method DisplayParsedFiles:Void() 'debug 'If displayOnce End Method Method AllFilesLoaded:Bool() Property Return ((filesQueued = FILES_NEEDED) And FileBuffersLoaded) End Method FileBuffersLoaded:Bool() Property For Local I:= 0 Until files.Length Local file:= files[I] If (file <> Null And file.Length = 0) Then Return False Endif Next Return True End Method FilesCompleted:Int() Property Local count:= 0 For Local I:= 0 Until files.Length Local file:= files[I] If (file <> Null And file.Length <> 0) Then count += 1 Endif Next Return count End '====================================================== ' Fields '====================================================== Field fileButtons:HTMLFileInputElement[] Field runButton:HTMLInputElement Field scaleUpButton:HTMLInputElement Field scaleDownButton:HTMLInputElement Field LoadMyMapButton:HTMLInputElement Field running:Bool Field readOnce:Bool Field generateButtons:Int = 0 Field AllDataList:String[] Field quitButton:HTMLInputElement Field bodyNode:dom.Node Field files:DataBuffer[] Field filesQueued:Int Field repeater:EventRepeater 'Image Vars Field map:Image Global MapSwitch:Int=0 Global MapRotate:Float=0.0 Global MapZoom:Float=1.0 Global xmap:Int=40 Global ymap:Int=40 Global ScaleFloat:Float=1.0 End ' Functions: Function Main:Int() New FileApp() Return 0 End you'll need to create a 'native' directory, at the same level as your monkey.data folder, with the following javascript function (file_to_databuffer.js) in it :-- function loadFile(file, buf) { var reader = new FileReader(); reader.onloadend = function () { var rawData = reader.result; if (rawData == null) { return; } buf._Init(rawData); } reader.readAsArrayBuffer(file); return buf } The 'LoadMyMap' button doesn't do as advertised just yet - if anyone can help with this it'd be appreciated ;) |
| ||
bookmarked, will look at it when i hit that point thanks for posting this. |