Recommended document structure. File Wrappers? Roll my own? - objective-c

I'm currently working out the best structure for a document I'm trying to create. The document is basically a core data document that uses sqlite as its store, but uses the Apple provided NSPersistentDocument+FileWrapperSupport to enable file wrapper support.
The document makes heavy use of media, such as images, videos, audio files, etc. with potentially 1000s of files. So what I'm trying to do is create a structure similar to the following:
/myfile.ext/
/myfile.ext/store.sqlite
/myfile.ext/content/
/myfile.ext/content/images/*
/myfile.ext/content/videos/*
/myfile.ext/content/audio/*
Now, first of all I went down the route of creating a temporary directory and placing all of my media in there. Basically creating the paths and file names '/content/images/image1.jpg' as I wanted them to appear in the saved file wrapper, and then upon save I attempted to copy these all into the filewrapper...
What I found was that the files were indeed copied into the wrapper with the file structure I wanted, but when the actual wrapper was saved, these files all magically disappeared.
Great.
So, I trashed my existing solution and tried to use file wrappers instead. This solution involved creating a content wrapper file directory when a new document was created, or loading in a content directory file wrapper upon opening a document.
When an image was added/modified, I created the necessary directory wrappers inside this root content wrapper (i.e. an images directory wrapper if it didn't already exist, or any other intermediary directory wrappers that needed to be created) and then created a regular file wrapper for the media, removing any existing wrapper for that file name if one was there.
Saving the document was just a case of making sure the content file wrapper was added to the document file wrapper, and the document would save.
Well... it did. The first time. However, any attempts to make any subsequent changes i.e add an image, save. Then replace image, save. Did not behave as expected, only showing the image from the first save.
So, my question is... first of all, which of the above approaches is the correct one, if at all, and what am I doing that wrong for them to fail.
And secondly, as I expect to be managing 1000s of images, is using file wrappers the correct way to go about things at all.

With that much media in play, you should likely give your users control over whether the media resides in the document or only a reference to the media is included in the document, and the media resides elsewhere, such as in a library/repository managed by your application. Then they could save out a (potentially many times larger) copy with all references resolved.
You might want to zip/unzip any directory so that users don't get confused trying to attach the document to an email. I believe iWork has been doing this with its document bundles for a while now.
As far as what you are doing wrong, no-one can say, as you haven't provided any code demonstrating what you are doing.
Why don't you create a one-off application that lets you select files on disk and saves those files in a document using a file wrapper? This would let you tackle this functionality without any interference from other issues in your application. Once you understand how to use file wrappers, you can port the code back or just write new code that works.

Related

Vaadin 8 multiupload with folder selection

I need to upload files and folders to the server while preserving the hierarchy. At the moment I am using a plugin multiFileUpload that allows you to upload multiple files at the same time, but it ignores the selected folders. I know that neither vaadin nor Html5 has a universal solution that works everywhere for uploading folders.
I'm ready to write my own solution, but climbed the Internet can't find a way to display file selection (perhaps there will a JavaScript call) but the main question - is it possible somehow to POST a request Vaadin's and upload files by way of creating subfolders in which they were?
You can only upload files, not folders. It's simply not doable.
You can upload any number of files, but they won't be structured into folders.
I see two possibilities how you could still achieve what you need if you really wanted to, even if it changes the user experience a bit:
Let the user upload a .zip file of his folder structure. When they upload it, you unzip it on the server side and have now access to all the files in the correct folder structure.
Let the user upload all his files within his folder structure. After all files have been uploaded, You display all the files in a TreeGrid where the user can recreate the original structure using Drag-and-Drop or similar.

custom file open with custom application only

I am working on vb.net application where I wanted to create and read a file. File will have specific extension for ex. .abcb the way I want my application to work is:
can create a file with .abcd extension
should read .abcd files only(and also application created files only so altered extension shouldn't be working)
.abcd files should show some garbage data when open in any other application(ex. word, notepad any image viewer etc.)
Now my application does 1,2(partly) step, i.e. it creates a file and load data also, it reads .abcd files only(not the altered files)
but created file can be read by other software's also.I tried searching a lot but have not found anything and don't know where to start.
Any help is appreciated!
if you don't want other programs to be able to read the content of your file then your going to have to mask it in some way, which is usually done with encryption.
assuming your not too worried about the key being compromised, the easiest way to accomplish this would be to generate a key with something like System.Security.Cryptography and use that key to encyrpt everything you send to the file and everything you read from it.
as for making your own file extension, you can make the extension of a file whatever you want when you make it:
Dim fs As FileStream = File.Create("/path/to/file/filename" & ".abcd")
the only thing that the extension does is tell the OS what progam to use when opening a file by default, which will probably be notepad since your making your own extension

Preventing other application from opening custom file vb.net

I have a text file. Now I have changed its file type from .txt to .abc. My VB.NET program loads the text into textboxes from that file. After changing the file type, however, other apps like NotePad and Word are able to open and read my .abc file.
Is there any way that only my application will be able to open/read from the file and no other app would be able to do so? What I mean is, suppose I have a PhotoShop document .psd file, no other app, rather that photoshop itself, can open it. How do I make my file unreadable by other apps?
There is no way to prevent an app that you don't develop from opening any file. The extensions are just there for helping us humans, and maybe a bit for the computer to know the default app you select for an extension.
Like you said, a .txt file can be opened by many many apps. You can open a .txt file with Notepad, Firefox, VSCode, and many others.
Same way, a .psd file can be opened by many many apps. You can open that .psd file with Photoshop, but also Notepad, Firefox, and VSCode, and probably the same apps as above.
The difference is which apps can read and understand the file.
In order to make a file not understandable by other apps, you need to make it into a format that cannot recognize, because you planned it "in secret".
Like Visual Vincent said above, you could encrypt the file in a way, or you can have a binary file, that basically only your app knows know to understand.
Since you dont own the app you want the file to be understood by, then you either have to accept that it can be opened by any app that can open files, or you can try to encrypt the file outside the app, or like zipping it with a password, and then decrypting or unzipping when you want to use it.
Firstly, any file can be read unless it is still open by a particular process or service. Even PhotoShop files can be 'read' by NotePad - try it!
So, an attempt at my first answer...
You can try a couple of methods to prevent opening the file, for instance, applying a file lock. As an example, SQL Server .mdf files are locked by the SQL Server service. This happens because the files are maintained in an open state, however; your application would have to remain running to keep these files open. Technically, though, the files can still be copied.
Another way is to set the hidden attribute for the file. This hides the file from the less savvy users, but it will be displayed if the user show's hidden files.
And my second answer: You refer to the format of files by saying only PhotoShop can read or write its own files (not true, but I know what you're saying).
The format of the file must be decided by yourself. You must determine how you are going to store the data that you output from your application. It looks like you have been attempting to write your application data into a text file. Perhaps you should try writing to binary files instead. Binary files, while not encrypted, as suggested by Visual Vincent in the comments to your question, still provide a more tailored approach to storing your data.
Binary files write raw binary data instead of humanised text. For instance, if you write an integer to the file it will appear as a string of four bytes, not your usual 123456789 textual format.
So, you really need to clarify what data you want to write to the file, decide on a set structure to your file (as you also have to be able to read it back in to your application) and then be able to write the information.

NSBundle, can it be used to save a project document?

I'm building a Mac OS X application that can be used to create 'projects'. When a user saves a project, they will be saving many resources: image files, text files, sqlite files etc.
I can either create a folder in Documents for each project, and within that folder I can place all the project assets, and just include a single project file that is used to open the project.
I've read about NSBundle which I'd like to use. But I've only read about them in the context of application bundles. Is it possible to use NSBundle in this way? Where the user only sees a single file, and can move it wherever they like.
Does it make sense to do what I'm trying, using NSBundle? Or is there another way to do this?
(I'm fairly new to MacOS X programming)
UPDATE
I believe iPhoto uses this method to store the "iPhoto Library", this is what I'd like to do with my application, is NSBundle what I should be looking into?
Yes, it is possible and was used in quite a few apps in the past. The method is described in this document. Once it's clearly declared in your app's Info.plist, Finder will show the resulting bundle as one file.
However, I can't recommend you to do that. Apple's own Keynote was using the bundle approach in the past, but it no longer uses it any more. Similarly, OmniGraffle (which is a diagramming app on OS X with a long history) used bundles to save projects, but it stopped doing that, too.
The reason is that the bundle is still seen as a directory by the non-Apple email software, or any browser, etc, although the Finder shows it as a file. It would be a mess if a user wants to attach your document in the bundle format to an email s/he is composing in Gmail inside a browser, say. That confused a lot of people.
So, it's possible, but I don't recommend it. One way out is to use the zipped bundle as the user-visible file, and to unzip it when the user opens it into a temporary directory. Then you can use NSBundle and/or NSFileWrapper apis to access files inside it.
Apple's File Wrapper sample seems to be what you want:
http://developer.apple.com/library/mac/#samplecode/PersistentDocumentFileWrappers/Introduction/Intro.html
It also demonstrates how to save a Core Data persistent store in the bundle. You can leave that part out if you just want to store resources.
The NSBundle class represents the application bundle, and can be used to access resources within the applicationm but you would you it for application data, not user data.
For each of the resources you mention, there's a way of saving this type, for example, for image files, you could use NSData to save the image data to disk, and for text files you could use the method writeToFile:atomically:encoding:error:.
You may very well want to take a look at Core Data (http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreData/cdProgrammingGuide.html), a very good framework for managing the user's data model, to see if this would fit your needs.

Objective-C / Cocoa: Uploading Images, Working Memory, And Storage

I'm in the process of porting an application originally in java to cocoa, but I'm rewriting it to make it much better, since I prefer cocoa a lot anyway.
One of the problems I had in the application, was that when you uploaded images to it, I had the images created, (as say an NSImage object) and then I just had them sitting in memory, the more I uploaded the more memory they took up, and I ended up running out of memory.
My question is this: if I am going to have users upload images to this application in cocoa, how should I go about storing them? I don't just want to copy the file paths, because I want what is saved to contain the images, etc. Is there any way to upload an image and copy it into a different place only for my application? Then load that image with the new path name as needed?
Only I would like it all to be consolidated. I'm going to implement saving by archiving one "master" object into an NSData*- so I'd like the images to be saved with that.
Is there a temporary location maybe where I could write the images to disk for my application, and then when I saved, they would all be archived into a single file? Also, how do I do this? Thanks.
If you only want to store the images temporarily, you can store the images in the temporary folder that you get by calling NSTemporaryDirectory(). You would then be able to load the images only when you need to display them.
If you want to save the images with your document then you should investigate using a package format for your document, so that the document is actually a folder containing your images and your archived data file. You can create a file wrapper containing all the files for your document bundle using the various methods of NSFileWrapper and then you would implement the -fileWrapperOfType:error: method of NSDocument in order to handle saving.
This would allow you to store the images unaltered and then lazily load them from the document bundle when required.