I have an ASP.NET web application that uses jQuery on client side.
On one of the web forms I have a bunch of controls to fill, and an upload control.
User can run upload while filling other entries on the form.
When user saves the form, all data including file is stored into database .
The question is what to do with uploaded file while user fills the form?
I have two possible solutions, but don't know which of them is more optimal
Cache uploaded file, and later, while saving, retrieve it and store into database with all other data.
Save file in temporary folder, and then read it.
What is the best solution for this?
Thanks in advance.
I think the most appropriate solution will be storing uploaded file in cache.
Here is the code
var fileKey = Guid.NewGuid();
var fileStream = new Byte[Request.Files[0].ContentLength];
Request.Files[0].InputStream.Read(fileStream, 0, Request.Files[0].ContentLength);
Cache[fileKey.ToString()] = fileStream;
The fileKey GUID can be stored in ViewState, or sent as the response to client.
Later, when whole form will be saved, cached file can be retrieved and stored into database with other data.
The good thing about this method is that if user navigates from the page cached file will expire, thus avoiding resource flooding.
We can set expiration time using
Cache.Add(fileKey, fileStream, null, DateTime.UtcNow.AddMinutes(10), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
function.
How about:
3: Store it in the database but marked as in an incomplete state
This could be a separate table, or the same table with a status column.
I fail to see the difference between the 2 options: what do you mean by caching the file? Isn't it the same as saving to a temp folder?
AFAIK, most sites will not start uploading until the entire form is filled up (what if your user cancels, or browses away?). They then display an interim progress bar ("please wait while we're analyzing your data...").
As a general design rule, receiving partial data at any point in time may lead to inconstant data later. If you must do it in steps, change your form to a wizard.
Like other people mentioned - you can simply upload it. You can do it in many ways:
Upload the files in a temporary folder, and when they finally say save or complete - you can move the file from that temp folder to the other folder where you'd usually keep regular files.
One more thing that you can do, whenever the user clicks on upload button for temporary files, is that you can check you temp folder and clear other files which have stayed there for more than 1-2 days/weeks so that way you know for sure you are not wasting space.
Perhaps, you can also have a timer on
your website that regularly cleans up
this folder. I'd say this is more
efficient and you don't have to wait
for users to come in and click on
upload button to clean up your space.
Related
I have a project in C# that needs to upload files in a page with a lot of others information.
Problems:
1 - File upload doesn't give any feedback for the user, so they can't know how long will takes (doesn't work with UploadProgress and UpdatePanel).
2 - Some validations I can't do with javascript (relationships for example), so if I get any error on the server side, FileUpload loses the file and the user needs to upload the whole file AGAIN.
3 - End user have a really poor link, so for 10mb will takes a long time (10mb is the maximum allowed).
Solutions (none of them works great):
1 - I can use a client side file upload with javascript (like uploadify) and get the percentage, but works as async method so I need to block the screen to don't allow the user to do another things. My worry is more about when I receive the file and save it, because I need to link this file with the other entity if not I will lose the bridge between the file and the entity. (Same happens with the AsyncFileUpload Control). This doesn't solve the problem number 2.
2 - Just do everything synchronous as FileUpload, when all the files arrive to the server, save the file and put all the informations that I need in HiddenFields, so if I get any error on the server side I can recover the file. The problem is that I can't give any feedback for the user while he uploads the file. This doesn't solve the problem number 1.
3 - Split all the files from the others entities (this will mess a lot the project) and upload file individually. The problem is that if I do that I need some mechanism to create the link between the file and the entity AND I can't allow to use the file more than once, so probably this will request a lot of resources to check it. This solves the problems listed but I think create another, complex for the user and a lot of new verifications for the system.
4 - Create 2 buttons, one button VALIDATE for validations on the server side (with no file uploads) and after this check, allow the user to click on the SAVE button. This doesn't solve the problem number 1.
Well, as you can see I'm thinking a lot about the problem but I can't find a really good solution. One that fits all my needs. Anyone have a idea?
PS: I have FileUploads inside repeaters as well, so the IDs are automatics.
I have some PDFs uploaded by the user and they are saved on hard drive. Those PDFs should actually only be visible by the user who uploaded. But at the moment it is not secure. If somebody guesses the name of the PDF, it can be viewed by anybody else too.
Eg: http://www.something.com/PDFs/abcghjiekm.PDF
This is a security threat. What I'd like to be able to do is have some kind of logic that processes the request to these PDFs and compare it with my DB to see if this PDF is actually belonging to the user who requested it. How can I do that?
Edit: I cannot use FileStream as my website is already up and running. I don't want to change all of the codebase and go into each and every aspx page to hunt where the PDFs are accessed.
You could handle PDF through an special HttpHandler in IIS instead of the StaticFile-Handler and check for Access-Rights.
IF you are using MVC a route like /PFDs/{file}.pdf with an Controller returning Content will do.
You could also use some sort of security-by-obscurity, which is less secure, but easier to implement. For example you could save the PDFs in a folder such as PDFs//abcghjiekm.PDF where the guid is the userId of the uploading user. This way guessing the right path for a given file is much harder.
I wouldn't recommend this method if you really need to protect private user data from unauthorized access, but if all that you're trying to achieve is some sort of error-protection (so that users wont access each-other files by mistake) this ought to do it.
If you need real security - I would recommend doing what Grumbler85 suggested.
I think you should use the FileStream, part of the Sql Server 2008 and above to store these files.
http://technet.microsoft.com/en-us/library/bb933993%28v=sql.105%29.aspx
Using it, the files area stored on disk, but in special place. And you have no problem i.e. when someone want to change any file.
I would like to write a Web Application that would have two buttons and directly from the browser would allow me to open two simple text files (using a File Open dialog box or something similar) and would then proceed to read in contents of those files and store them inside of a two strings. The key point here is that the exact files used to read from I don't known at runtime so it would be up to the user to select the files.
The goal is to be able to later compare those two strings but that part I already know how to do. My questions is this - is it even possible to do this inside of a Web Application (i.e. to call a File Open dialog box to allow the user to select files to read from) or would security limitations or some other Web Application related constraints prevent it from being done?
If it is possible, I would appreciate some sample code describing how to open files and how to read in contents of the selected files into strings. Othwerwise, I would like to know if it's not possible and I should consider doing a desktop application or try an entirely different way.
Thank you!
It is possible, but you would wind up having to upload both of the text files to the server and read the files into strings server-side.
All you would need to do is add two separate FileUpload controls to the page along with a button to post the files to the server.
If you don't want the page to refresh, you could always do the comparison via AJAX using the AsyncFileUpload control from the ASP.NET AJAX Toolkit.
Update
Reading the contents of the file should be relatively easy (as long as they are plain text):
var reader = new StreamReader(fileUploadControl.PostedFile.InputStream);
var contents = reader.ReadToEnd();
One way is to use the ASP.NET AJAX AsyncFileUpload control.
http://www.asp.net/ajax/ajaxcontroltoolkit/Samples/AsyncFileUpload/AsyncFileUpload.aspx
In order to access the files from the server-side code (C# code) you'll need the user to upload them. The standard way to do this (and, for security reasons, the only way upon which you should rely) is with a file input element. In ASP.NET, you can use the FileUpload control.
You would essentially give the user two of these controls with which they can upload the two files. Then you'd read their contents on the server, save them however you wish (as files, to a database, just in Session for temporary use, etc.) and perform your logic on that data. Then build your output (the comparison part, which you said you have already) to display on the page refresh.
Be mindful of concerns such as what to do if the user tries to upload non-text files, very large files, etc.
That is not possible alone with JS. You would have to build a file upload (and store session information) or use Silverlight and a Javascript-Bridge to your Web-Application.
Here's an example for a FileOpenDialog in Silverlight: http://www.silverlightexamples.net/post/Open-File-Dialog-in-Silverlight.aspx
Here's an exmaple for a file upload via C#/Webforms http://support.microsoft.com/kb/323246
I have a simple form which the users can use to upload images. It has a preview button so when User selects an image and clicks on preview, a postback occurs and I save the image to temporary folder and resize it and show it on the page. from there, the user can either submit form or edit the form. If he submits, everything is okay, I copy the resized image into correct folder.
If he clicks edit, and chooses another image, I need to delete the uploaded files (both original and resized) and If I do this:
File.Delete(HostingEnvironment.MapPath(TmpDirectory + PostImageName + ".jpg"));
File.Delete(HostingEnvironment.MapPath(TmpDirectory + PostImageName + "_small_.jpg"));
I get an exception saying some other process is using the image and It cant delete. (even after postback!)
and Also, if, instead of deleting that file, I try to save the new image with the same name so that it would overwrite, it still throws the error because file already exists.
There is no limit to the number of times the user can edit / preview so I cant save files incrementally (it doesn't even make sense to do this)
Also, after the postback, when the user goes back to edit mode and views the form the file upload control is empty. how can I get the file upload control to retain the value? all the other textboxes and text areas and checkboxes behave properly.
to summarize these are my questions:
1) how on earth (or rather, in c#) can I delete files without getting that exception?
OR
1) how to overwrite files?
2) how to make the file upload control retain its value between postbacks.
Thanks.
The exception talks for itself : Your file is still being used/opened by another process, i.e. thread, that you have launched. I bet it is the process by which you open the image file for reading. Make sure you have closed the relevant stream, ten bucks that it will solve your issue.
Why are you using a Bitmap to open the file on the server side? You should simply stream the "file" using
Response.TransmitFile(physicalFileNameAndPath).
Where TransmitFile expects (as a string) the physical file path and name.
The problem stems from the the way you send the file to the client. The file is still "locked" by the previous step. If you fix this, you'll be able to delete the file if needed.
I've not used the FileUpload control but it looks like you're using ViewState (which is what helps retain the values in the fields after postback. Either the FileUpload control does not support ViewState or you've not configured it to use ViewState.
you could assign the required property of the FileUpload control with the correct "value" so it shows what you've expect. This would mean that you'd have to capture the said value when the form is posted and simply re-assign the value back to the FileUpload control's property during the DataBind.
Make sure that your current
process doesn't have a write handle
open to the files in question
If there are no handles then try
turning off your virus scanner; an
overly aggressive virus scanner
could be taking a lock on those
files just after they have been created. This might be preventing you from deleting the files.
I want to make a very simple CMS for my sites. So what I am thinking is this a user logs in and a list of their pages shows up. Now they change their ends and save it. My C# code would then write over the file/section.
So I don't think it would be to bad to do this however I am not sure about how it works with read and write premission and how to set it up.
Like I want the user to only be able to read and write to their files they own.
So if User A has Page1.html and Page2.html they can only read those files and write to those files they can touch User B's page3.html and Page4.html
So how would I setup this up?
Thanks
When you create your list of files, you will be reading that list from a database repository. Include in that code conditions that allow only those records for which the user has permission.
The most straightforward way to do this is to create a table with two columns: UserID and DocumentID. A presence of a record in the table indicates that the user has permission to that particular document. Add records to this table that give the user permissions to the appropriate documents.
Then, when you read the documents from the database, you can join this table to the documents table via the DocumentID, and filter the table by UserID. This will return only those records for which the user has permission. You can then use that set of records as the basis for the list of documents that you display to the user.
You could employ a cms the SharePoint way. You begin with a base file on the network. If a change to it is made then the page is stored in a database. each subsequent change is a db change and the application renders the last entry in the table for that page.
this does two things. first, you can see revisions and re-instate them. you can see a complete history of the page, who made the changes and when.
it also allows you to lock pages within the database and assign roles/users against the pages. you can then apply a decoration to the controller which checks rights and either renders the page or displays a access denied page and then log the attempted access to the page.
i know this sounds complex but can you foresee a time when after you've gone live with your cms that the client is going to want more from it? you need to implement a solution that's adaptable to needs.
if it's worth writing then it's worth writing well.