Skip to main content
Participant
January 13, 2011
Question

How do I use a FileStream with an IFilePromise without knowing the File?

  • January 13, 2011
  • 2 replies
  • 911 views

I've finished the implmentation of my project using Async IFilePromises by extending the ByteArray class. I can drag out of my application and files are created by copying bits over the network, etc. The issue I'm running into is that because I used the ByteArray as my dataprovider, files are stored "In-Memory" until the Close event is fired.

My application routinely copies files around 700 MB and up to 2 GB. The implementation quickly causes out of memory errors. That said, if I change the implementation to use FileStreams then the files are written directly to disk and memory is exactly where I want it to be.

The issue is that the FileStream requires a File object when it's FileStream.open(File, FileMode) method is called. If I manually create a file and use it, then everything is fine, but doing that defeats the purpose of the FilePromise. I lose all the information about where a person dropped the file.

So how do I get access to the File object that is created for each FilePromise? I know one is created by inspecting the call stack when the IFilePromise.open() method is called and inspecting the caller MacFilePromiseWrapper._file.

I've tried simply returning a plain FileStream instead of an extended class in the IFilePromise.open method, but that still gives the same error result when I try to write to the stream (says that the stream isnt open yet).

I would have expected the MacFilePromiseWrapper / FilePromiseWrapper to intelligently handle the returned IDataProvider and perform any "open" and "close" it needed. Please tell me I'm just missing something obvious. I'm so close to being done with this project and I don't want to have to rewrite this using a native implementation. The performance issues (memory usage) will cause me to do just that if I cant figure this out.

Thanks for any help,

Jared

This topic has been closed for replies.

2 replies

Participating Frequently
January 24, 2011

Do you have any thoughts on how to read a file locally as though it's streaming in via the network?  I am doing something not to dissimilar from you, but in my situation the user has to select a local file that is huge and the intent is to break it up and upload it in chunks. So, the uploading app needs to not "read" the local file, but just scan through it some chunk at a time writing those bytes to a small local file for upload.  I can't seem to get fileStream to take a reference to the File without attempting to read the whole thing into memory (which is not even possible, given that the files frequently excceed available memory).

If you have any thoughts, I'd be very grateful.

Game_YetiAuthor
Participant
January 27, 2011

How are you sending the bytes across the network? In my application I opened the file via a file stream and then read chunks of the file, writing directly to a network socket.

Is this the same thing you're doing, or are you trying to upload via a different method? Essentially do you need it in a real file (temporary or otherwise) before you can ship it across the network? I should be able to provide you with a bit of sample code to get you on your way either way, but knowing your end goal will help.

Also, what is the endpoint you're writing to? Mine was Adobe Air Client -> iPhone.

Participating Frequently
January 28, 2011

There's actually another thread where this question was answered for me, thanks.

The solution is that it's imperative to set the readAhead property because without it Flash tries to read the entire file into memory and chokes around 1 gig.

Once you set readAhead to something manageable it's then a synch to openAsync the file and read it using readBytes. The only other thing to keep in mind (which was not intuitive) was that the second parameter of readBytes needs to always be 0. You don't need to keep track of where you are in the overall file and pass that in as the starting point. The method deals with a data slice and you are always starting at the 0 point of that slice.

Game_YetiAuthor
Participant
January 14, 2011

I have resolved the issues myself.

I had the idea of an IFilePromise / IDataInput backwards. The way I thought it worked is that what you were "writing to" when you wrote into a ByteArray and fired of progress events was simply a pipe to a file handle on the disk. That's backwards.  What really happens is that the thing you're writing to is a buffer for the IFilePromise. Firing the open/progress/close events let the file system know that it's safe to pull up to IDataInput.bytesAvailable out of your buffer and write that to the disk and the buffer you write to can be a ByteArray, Socket, FileStream, etc.

The confusion was compounded by my attempts to use FileStream as the IDataInput. What I was doing for "testing purposes" was creating a temporary file and writing my bytes to it. The file handle created by the FilePromise would immediately disappear, so I thought it meant I needed to somehow get access to that handle so I knew where to send my bits using FileStream.open(File, FileMode).

I was really close, but had a mistake in there.  I was on the right track with opening the FileStrea and using the temporary file, but I opened it with the wrong FileMode.

I used FileMode.WRITE because I thought I was writing to the disk only. When I switched it to FileMode.UPDATE (which is read/write) then everything worked as I needed it to.

So to summarize, to use a FileStream as the IDataInput for an IFilePromise you need to:

  • Create the FileStream object and return it when the IFilePromise.open is called
  • When you get bytes off your network, etc, dispatch the OPEN event
  • Open the FileStream object with FileMode.UPDATE and use a temporary file provided by File.createTempFile(), store it for later
  • Write bytes to the FileStream and send out the proper ProgressEvent.PROGRESS events
  • Dispatch the COMPLETE event when you're done
  • the IFilePromise.end() method will be called and you have an opportunity to close your FileStream and to delete the temporary file that was created

I hope this helps someone that runs into a similar issue.

chris.campbell
Legend
January 19, 2011

Thanks for sharing the solution that worked for you!