concurrent reading and writing image files (asp.net, but applies to most web languages) - asp.net

I have a .jpg file which represents the current image from a webcam. User's will be downloading this file at an interval of once a second. Because there could be dozens of users reading it, this could be dozens of times a second (which is normal for any web server).
Problem is, this image is updated by a 3rd party application also once a second which "spiders" my local networks webcam portal image. This is so we can build our webcams into our current administration panel.
The problem I am already finding is ASP.net sometimes gets an error it can not access the file because it is open for write permissions by the bot. Likewise, the bot can not access it because IIS is feeding it to the user.
The bot uses io.streamwriter to save the data to the file, and my script uses Response.WriteFile to send the file to the script. (I need to use an actual ASP.net page with a JPG content-type that feeds the file to make sure only users with a active session can view the JPG).
My question is what is the best practices for this? I know why it's happening but what is the best resolution for this? Would storing as a BLOB in a database maybe be smarter since databases are created for concurrent read/writing already? Is there an easier way of doing this with a file I have not thought of yet?
Thanks in advance,
Anthony Greco

Using a BLOB will work if the readers use SNAPSHOT isolation model (SQL Server 2005 and up). See Download and Upload images from SQL Server via ASP.Net MVC for how to stream an image from a BLOB, and see Understanding Row Versioning-Based Isolation Levels for a lecture on SNAPSHOT.
But using a BLOB may be overkill, you could get away with something much simpler. For instance, if you only have one ASP.Net process, then you could have a global volatile variable for the current file name. The writer writes the JPG into a new file, and then updates the global 'current' file name with an Interlocked.CompareExchange operation (it has to be Compare because a newer writer might actually finish faster, outrun a previous writer, and you want to preserve the latest update). There are still some issues left to solve (find out the file name at startup, clean up old files etc) but they are all fairly ease to solve.
If you have a farm of servers, or multiple ASP.Net processes serving the site, then things could get complicated. I would still do a rotating file name and do a try-and-error approach (try to respond with newest file, fall back to previous older one if conflict is detected).

You could get the bot to write the data to a different filename and then do a delete and rename to the filename being served by ASP.Net. This should reduce the file lock time down to the time for a delete and rename to occur. To clarify:
ASP.Net serving image from "webcam.jpg"
bot writes image data to "temp.jpg"
when last image byte written, bot deletes "webcam.jpg" and renames "temp.jpg" to "webcam.jpg"
ASP.Net should check "webcam.jpg" exists, if not wait 10ms (or suitable small increment) and check again.

Related

How to be sure about an uploaded file is not a virus in ASP.net?

I saw this question:
ASP.NET File Upload: how can I make sure that an uploaded file is really a JPEG?
and similar questions about being sure of the file being uploaded through asp:FileUpload control in ASP.net is really image. But What If users upload virus-infected images? How can I be insured of the image files being uploaded via my ASP.net application does not affect the files in my web app folder and/or images uploaded by other users?
As long as you don't serve it back to anyone as anything other than an image (content-type) and never trying to execute (.exe) the file you'll be fine.
Most anti-virus software run whats known as an "on-access scan". That is, when a file is changed, it automatically scans that file.
So save that file to the file system and let your server's anti-virus software do the work for you.
I'll take what is likely a somewhat controversial position.
There is no way to know with 100% certainty what the intent of a file is, be it good or evil. It is impossible. AV scanners give you a slice of data but they can't give you 100% guarantees either. No one can.
Given this reality, you need to build your app assuming that all files uploaded are bad. Yes, scanning is still fine and will filter out a bunch of stuff. But it will never be 100%. Is it 99.999% or 20%? Who knows. Does it really matter?
I would build any app today assuming that all user supplied content is bad. Very bad. Hostile bad. Because eventually it will be if you make it. And when it is, you'll be ready for them...rather than all the people that have to rearchitect their app because they made bad assumptions early on.
With a bit more data about your exact concerns, I'd be happy to comment on them more specifically...
As a side note, In older version of IIS (6 or prior versions) It could be possible to change FileName to the real malicious file name after save the file with original filename. Which has possibility to be read and execute regularly by the server.
E.G. set the file name like: file.asp;.jpg or file.asp%00.jpg etc...
It also has a possibility to change target directory by manipulation of file name. Which is extremely dangerous
E.G. newfolder.asp::$Index_Allocation or etc...
There is also some new way of attacks. Read more here.

Transferring files from old dedicated server to a new one

Using Classic ASP (stop tutting), I need to build an application that transfers high resolution photos from one server to another, around 360,000 including the thumbnails to be exact. The application will be called via a Windows schedule and will run as a background process.
What is the best way to achieve this, keeping performance in-mind? The last time I built a monster script like this was transferring and converting database tables for over one million rows, the application started really fast, but then after 25,000 records it went really, really slow! So I want to avoid this.
Obviously it will be a cross-domain transfer, so I was thinking about using an ASP/FTP component, and one-by-one, grab a file, send it, and record its success in a DB table so it knows what is has done so far.
Is it best to process one file at a time and refresh, so it doesn't abuse the server's resources, or should I process 1000 at a time, or more? I want it to be as quick as possible but without clogging up the server.
Any help/suggestions would be gratefully received.
I think is best to do one file at a time because if the connection goes down for a brief period of time you don't lost the files that you have already sent.
Even when you are using ASP Classic you can take advantage of .net for uploading the files using the FTP client classes in .net and avoid purchasing/installing a third party component. Surely .net is already installed on the server.
My process will look like this:
Upload 1 file using FTP (better performance)
If successful call an ASP page that records the action in the remote DB
Wait a second and retry up to 3 times if error uploading
Proceed to next file
If the process is clogging the server, you can put a brief pause between each upload.
i have something like that running in Classic ASP, it handles tenthousands of images without problem.
On the server that houses the images I run a (vbs)script that for each image
Makes a text-file with metadata
Makes a thumbnail and a mid-sized image copy on the second (web)server
The script runs continuously and only checks per folder and file if the files are present on the webserver and if not creates them, No need for a DB.
Between every check It sleeps a second. Like that the load on the server is only 2%. I use iPhoto in command-line modus to extract the metadata and images but you could use a library for that.
So these three files are stored on the webserver in a copy of the mapstructure from the first server but without de full-sized images.
On the webserver you only need to be able to browse the thumbnails and visualize the metadata and mid-size images.
If the user needs the full-size image he clicks the mid-sized which has as url the file on the first server.
Upload all the files via FTP
Create a CSV file with all your data
Pull it into the DB in one go
The amount of network handshake over 360,000 individual transactions would be the bottleneck.

Advanced image editing off the web

I'm building an app in ASP.NET that will store some pictures of objects. The pictures will be uploaded by suppliers and downloaded by subscribers. In between, they will have to be edited before becoming available to subscribers.
The editing involves creating a cropping path tightly around the object in the picture, in which some advanced desktop image software will have to be used I suppose.
My problem is in exchanging pictures between my ASP.NET app and the desktop software in a manner that is easy and transparent for the user.
I've done some thinking and I've come up with:
- Manually downloading and uploading the image (Not much user friendly...)
- An image editing program that can upload to a web service (Haven't found yet...)
- Develop a plug-in for an image editing program (Too advanced...)
I'd appreciate any suggestions you may have, thank you!
It sounds like you need some automation to move files between the web server and a file share. I am assuming that the number of images that need to be processed is pretty large, because if it's not, then the overhead of downloading/re-uploading each would not be that much.
So do the following:
1) Create an API for your web app that lists files that are available, or new files since some date/time, or files that have been marked as "new". The API should probably also allow marking a status on them (so you can tell it when you've finishing pulling something down, and it won't be offered again) if you don't want to trust date/time as an indicator of it being new.
2) Write an app (non-web) that runs on a schedule and uses this API to automatically download files to a shared filesystem area in your local network, and marks them as "downloaded"
The app should also monitor these files (the ones it downloaded & saved to your local share) for changes, and if changed, upload them back to your web app. To do this you may need to keep a database of filenames and modification dates/times.
This shouldn't be too hard to write in whatever language you are using for your web (assume c# or vb). By "API" I just mean, a web page that provides a list in a standardized format (e.g. json) that you can parse with your automation application, and another page that allows posting the file back for re-upload.
I'm assuming that the web server is not your own, or generally, you can't simply have it save the file uploads directly to some area where your image editors can access them. Otherwise you could just do that.
Meanwhile I came out with another possible solution.
I'm thinking of having our own windows app on the editor's computers. This app will be associated with a custom extension. When an editor downloads a file (with this extension) for editing, it will be opened in our application which in turn will open the image in some editor program.
This app will be monitoring the files for changes, and in such case, it will upload these images.
Any thoughts on this?

ASP.NET - fast Segmented download of file through webservice

Im doing this project where i need to download files through a webservice (images, videos). The download MUST go through an existing webservice. The existing webservice was made when there were no need to upload and download files but the project has changed and now we need to do It through a webservice.
Right now I have implemented the download as a method that returns a byte[], I open a streamreader and resds the entire file into a byte[] and returns it to my method. This is working file on small files <~1Mb, above it takes too long time. I want to show some progress (e.g. when the user downlaods a 20Mb video) which i cannot do right now. And i want to make it download much faster (is a strategy to use multithreading and several threads that downloads a part of the file?). It is within a WPF application i need to do this.
Any ideas on how to approach this?
You can't do what you want to do using old ASMX web services. They will buffer the input internally, several times.
You need a way to move to WCF, at least for this new function. You can keep the old code, but you need a new, WCF service to properly handle the new.

MySql Audio Library

I'm coding in ASP.NET and want to store audio files (.mp3, or smaller formats) in a MySQL database; which, I can then retrieve based on certain conditions. Is this possible? Are there any preferred methods to having Audio files on your web pages (besides embedding them in the HTML).
Most solutions that store files in a database do not scale well, but you can certain store audio files, or any other type of file, as a blob (binary large object) in MySQL. You can create an ashx handler that performs the retrieval from the database and writes the content to the ASP.NET output stream as raw binary data. You can then create links that point to the ASHX handler and perform any query logic you want in there based on URL parameters.
If you are using a MySQL database, it seems to do well (at least in my experience) with blobs. It takes a relatively short time to load the MP3 and if you tune your database for audio, you can probably even get better performance (I pretty much use default settings).
One thing to remember is that you define the MIME-type so that users know what they are getting when they click a link to access your MP3.
Again, all of this is my own experience. YMMV.
I prefer to store large files outside of the database, unless there is some overwhelming need to keep everything there.
You could store the location of the file in the database and have the files outside of the webapp directory, so they can't be accessed directly.
Then, in the url for playing the music you can just have a cgi program that will just send that data to the browser, with the correct mime type.

Resources