I'd like to hold a collection of uploaded files for a user (where there might be multiple requests for each file, or even multiple requests per-file for chunking), but I'm struggling to find the appropriate scope. Once they're done, another request will say so, and the collection will dump its data to physical files and a DB entry and empty itself.
Ben here: http://buildstarted.com/2011/07/17/asp-net-mvc-3-file-uploads-using-the-fileapi/ uses a static collection, but that would be inappropriate for multiple users.
You need to store the files somewhere semi-permanent. Session could be reset along with the app domain, so you can't rely on it 100%.
Just have a separate file/db location or flag which lets you know the whole set of files is not completed.
Related
Let us say that I have a rails app, and I have multiple files stored in the rails app within the public/images directory.
Question: Is there a way an end user could get access to images stored within the public directory without the user happening to brute-force guess what the image file names are?
For example: is there some trick where a user could list all the files within the public directory of a rails app?
I am aware that you NEVER store sensitive files inside the public directory because it has no access control. I'm just curious if it is possible to access the public directory contents in some clever way without already knowing the directory/file structure. I'm wondering if there is a clever way to derive the directory/file structure within the public directory.
If, and that's a big "if", your server is configured correctly and does not have directory indexing turned on then there's no way you can enumerate a list of files. In order for this to be the case you must know how to configure your server properly. Many servers, especially Apache httpd, turn on directory indexing by default so you must explicitly disable this. You must also periodically test that it's disabled as sometimes a simple software update can revert settings to defaults.
This comes with the caveat that there is no guarantee that a high-impact vulnerability that allows directory traversal and enumeration may not occur in the future. Anything in public can be retrieved directly if the name is known. Any other file can be retrieved if there's a remote-code execution bug (RCE). Though these are very rare, it has happened to Rails before and could happen again.
The attack you want to defend against is dictionary attacks, or brute-force enumeration if there's a pattern to your ID values. Using a random UUID creates way too huge a space to search, but a short name like /profile-images/xBv.png invites people to probe.
I need to keep my data separately in different stores(user profiles). What is the best way to achieve this? I'm going to play with Persistent Object Stores in runtime. Should I simply remove() the current one and addPersistentStore() to make a new or to use the early created instance.
I would have one core data stack (using NSPersistentContainer) for user management. This stack would have the basic account details and the name of the sql file. (Store just the sql filename NOT the full url path, as the path can change in rare circumstance such as an iTunes restore). This would be used for the login, or select account page.
Then I would setup a second core data stack using the sql file name that was stored in the user account object. This would be the main stack used by the application. If you need to logout, then tear down the second stack and start over. Removing and adding store is a bad idea, as it won't deal with the row cache or other managedObjects that are floating around.
Or you could simply have one core data stack and manage the relationship so that every object belongs to a user object. Then you would manage your fetches to only look at objects belonging to the correct user.
In my project, a user is uploading a text file, that needs to be read.
File, can be of any size, the file I am using is 1 MB and has ~1500 lines. The file can be bigger as well. Hence instead of putting all in db, i thought of processing the file and retaining the data in instance variable.
But instance variables are not available across HTTP request. Hence what are the options available to me to retain the instance variable values across HTTP request.The other reason for not choosing DB was, I dont need the data to be persisted. As long as user is logged in, data needs to be present for that time duration only. Once user is logged out, I can discard the data.
Please let me know if you need further information.
As #xyious advises, I would say avoid storing that much data in session, it is just not a good practice. You could, however, do the following:
Setup a system-wide configuration setting that holds a path where you store temporary files, in this case, the files uploaded by the user
Generate a random (maybe with SecureRandom.hex) filename when the user uploads the file and store this file in the path mentioned on point #1
Store this random filename in the user session, that way, even if you change between requests you can still access the filename
On each request, whenever you need to process the data, pull the filename from the user's session and join the path of the setting of #1, read the file from the filesystem and do the processing as necessary
Add a callback on your login/sessions controller so that when a user logs out you go and find the filename and delete it before logging out, that way you don't keep unused files around
I would advise against it, but you could store the data in a session variable, or in a cookie.
Why would you need that much data to be stored while the user is logged in ? Is it possible to just save important bits ?
Using instance variables to store content is not a right approach since you don't have a limit on the size of file uploaded and you end up passing the data everytime.
Firstly, decide something on the size limit since you expect text file from users and then upload the file temporarily with a reference path in DB. This file can be cleaned up when required and will make accessing the content simple. To further improve this, enable caching mechanism and setup a caching server for the uploaded files.
If you are not fine with this then other option i can think of is using session variables which is already suggested. So this data will stay per session which fits your requirement. you can just session[:file_Data] = "put parsed content here"
I have a system I've built in MVC 3 that currently provides a yearly submission cycle where the system proceeds through a serious of seven steps tied to dates stored in the web.config as AppSettings. However, each year, I always have to roll the system back and forth between previous steps in order to accommodate the end users. I would like to give the administrator the ability to control the system status without having to contact a developer. What is the best way to do this?
I plan to build a page with proper validation that lets the administrator set the dates. I've considered a couple options of how I should store those date, but none of them seem correct. Our entire permission system uses these dates, and various bits of text on the pages turns on and off based on what period we're currently in.
So far I've come up with two options:
Option 1: Create a database table – This was my first thought. I’ve set up properties on the MvcApplication class in the global.asax and pulled them from the database. Using a lazy loader, I can set the properties the first time they're needed. However, when they change in the database, I don't have a way to force the system to “reset” and read the date changes. If I do this action on Begin_Request(), I'm constantly opening the connection and resetting the properties for each file that the web browser opens on the server, regardless if it's static content or not.
I could directly fetch the dates from the database every time I need one of the dates, but then I'm having to redo a lot of functionality to reduce repeated database calls. I'd like to cache the dates for each request, and only pull them when I need them,
Option 2: Allow editing a config file through the application – I've looked up how to split the web.config file so I can have a separate file that just contains the appSettings. Then I could just update the new config file from a controller action. I think this would work nicely, and not require me to rewrite any of the existing functionality, but it feels like I would be introducing a bad design pattern into the code.
I'd vote for the database. For the sake of performance you can cache those parameter values in a static class inside your app and provide a method to reread them from DB in the same class. So:
When a user makes request, check if those properties are already cached. If they are - use cached values, if no - read them from DB
When administrator makes changes to those parameters - store them to database and enforce your static caching class to reread them from DB.
I would suggest an approach that doesn't care whether the settings are stored in database or key/value pairs in config file.
Since you want the settings to be accessed globally by all users you can cache the settings and the cache implementation should be generic and distributed. There are plenty of online resources available how to create such an interface.
Since you want the cache to be sync with the underlying data you have to set cache dependencies (AppFabric won't supports sql cache dependency see this thread, while NCache supports both sql and file).
I would store the values in a database and use a distributed cache to persist the data across the web farm. MS AppFabric Caching has worked well for me. You will need to implement a standard caching pattern (check the cache, if null load from db and insert into cache).I would probably just create a static Load() method that abstracts this logic away. When the admins update the db you could update the cache or just delete the cachekey.
Therr are other considerations to be added to performance. Namely if you modify the config file thr application pool is re iniyializrd, while the database solution doesnt cause application reinitialization
...so do you need to re initialize the app after the changes or not?...If there i no way to avoid the inizialization whitout drastic changmes to the application ptobably the config filr solution is better
I'm just starting to learn ASP.NET MVC and I'd like to know how I can retain model objects between subsequent requests to controller action methods?
For example say I'm creating a contact list web app. Users can create, update, rename, and delete contacts in their list. However, I also want users to be able to upload a contact list exported from other programs. Yet I don't want to just automatically add all the contacts in the uploaded file I want to give the user a secondary form where they can pick which uploaded contacts should be actualy added to their list.
So first I have a ContactController.Upload() method which shows an upload form. This submits to ContactController.Upload(HttpPostedFileBase file) which reads the file that was posted into a set of Contact model objects. Then I want to display a list of all the names of the contacts in the list and allow the user to select those that should be added to their contact list. This might be a long list that needs to be split up into multiple pages, and I might also want to allow the user to edit the details of the contacts before they are actually added to their contact list.
Where should I save the model objects between when a user uploads a file and when they finally submit the specific contacts they want? I'd rather not immediately load all the uploaded contacts into the back end database, as the user may end up only selecting a handful to actually add. Then the rest would need to be deleted. Also I would have to account for the case when a user uploads a file, but never actually completes the upload.
From what I understand an instance of a controller only lasts for one request. So should I create a static property on my Contact controller that contains all the latest uploaded contact model object collections? And then have some process that periodically checks the age of these collections and clears out any that are older then some specified expiration time?
A static property on the controller is trouble. First off, it won't work in a web farm and second it you'd have to deal with multiple requests from different users. If you really don't want to use your database you could use the ASP.NET Session.
No, you don't want a static property, as that would be static to all instances of the controller, even for other users.
Instead, you should create a table used to upload the data to. This table would be used as an intermediary between when the user uploads the data, and completes the process. Upon completion, you copy the contacts you want to keep into your permanent table, then delete the temporary data. You can then run a process every so often that purges incomplete data that is older than a specified time limit.
You could also use the HttpContext.Cache, which supports expiration (and sliding expiration) out-of-the box.
Alternatively, and perhaps even better (but more work) you could use cookies and have the user modify the data using javascript in her browser before finally posting it to you.
However, I'd strongly recommend to store the uploaded information in the database instead.
As you pointed out, it might be a lot of data and the user might want to edit it before clicking 'confirm'. What happens if the user's machine (or browser) crashes or she has to leave urgently?
Depending on the way you store the data the data in this scenario will probably be lost. Even if you used the user id as a cache key, a server restart, cache expiration or cache overflow would cause data loss.
The best solution is probably a combination of database and cookie storage where the DB keeps the information in a temporary collection. Every n minutes, or upon pagination, the modified data is sent to the server and updated in the DB.
The problem with storing the data in session or memory is what happens if the user uploads 50k contacts or more. You then have a very large data set in memory to deal with which depending on your platform may effect application performance.
If this is never going to be an issue and the size of the imported contacts list is manageable you can use either the session or cache to store the dataset for further modifications. Just remember to clear it when the user has committed the changes, you don't want a few heavy datasets hanging around in session.
If you store the dataset in session using your application controller then it will be available to all controllers while it is needed.