7

I'm new in Web Api and I'm working on my first project. I'm working on mobile CRM system for our company.

I want to store companies logo, customers face foto etc.

I found some tutorials on this topic, but unfortunately some of them was old (doesn't use async) and the others doesn't work.

At the end I found this one: http://www.intstrings.com/ramivemula/articles/file-upload-using-multipartformdatastreamprovider-in-asp-net-webapi/ It works correctly, but I don't understand a few things.

1) Should I use App_Data (or any other folder like /Uploads) for storing this images, or rather store images in database?

2) Can I set only supported images like .jpg, .png and reject any other files?

3) How can I processed image in upload method? Like resize, reduce size of the file, quality etc?

Thank you

Stepan Sanda
  • 2,322
  • 7
  • 31
  • 55

3 Answers3

5

1) We are storing files in a different location than app_data. We have a few customer groups and we gave them all a unique folder that we get from the database. Storing in database is also an option but if you go down this road, make sure that the files you are saving don't belong directly to a table that you need to retrieve often. There is no right or wrong, but have a read at this question and answer for some pros and cons.

2) If you foollowed that guide, you can put a check inside the loop to check the file ending

List<string> denyList = new List<string>();
denyList.Add(".jpg");

foreach (MultipartFileData file in provider.FileData) 
{
    string fileName = Path.GetFileName(file.LocalFileName);
    if(denyList.Contains(Path.GetExtension(fileName))
         throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);

    files.Add(Path.GetFileName(file.LocalFileName)); 
}

3) Resizing images is something that I have never personally done my self, but I think you should have a look at the System.Drawing.Graphics namespace. Found a link with an accepted answer for downresize of picture: ASP.Net MVC Image Upload Resizing by downscaling or padding

Community
  • 1
  • 1
Binke
  • 897
  • 8
  • 25
  • Hi, thank you for your response. You answered most of my questions :) Unfortunately there is one more question about your posted code. You are using provider in foreach. But when you are loading data from provider, the file is already saved on the server. So if it's unsupported format, you send error back, but the files stay stored on server. – Stepan Sanda Jan 26 '14 at 20:16
  • Hi Sandak. Just read the code from the site you linked and it looked like the files.Add was the part where the file was saved, but throwing the error before saving the file would be recommended, as you mentioned. You may need to examine the Request.Content before creating and reading the data into the provider to avoid saving the file. – Binke Jan 27 '14 at 08:17
1

None of the questions are actually related to Web API or REST.

  1. If you are using SQL Server 2008 or newer the answer is use FILESTREAM columns. This looks like a column in database with all its advantages (i.e. backup, replication, transactions) but the data is actually stored in file system. So you get the best of each world, i.e. it will not happen that someone deletes the file accidentally so database will reference an inexistent file, or vice versa, records from database are deleted but files not so you'll end up with a bunch of orphan files. Using a database has many advantages, i.e. metadata can be associated with files and permissions are easier to set up.
  2. This depends on how files are uploaded. I.e. if using multipart forms then examine content type of each part before part is saved. You can even create your own MultipartStreamProvider class. Being an API maybe the upload method has a stream or byte array parameter and a content type parameter, in this case just test the value of content type parameter before content is saved. For other upload methods do something similar depending on what the input is.
  3. You can use .Net's built in classes (i.e. Bitmap: SetResolution, RotateFlip, to resize use a constructor what accepts a size), or if you are not familiar with image processing rather choose an image processing library.

All of the above work in Asp.Net, MVC, Web API 1 and 2, custom HTTP handlers, basically in any .Net code.

user3285954
  • 4,499
  • 2
  • 27
  • 19
-2

@Binke Never user string operations on paths. I.e. fileName.split('.')[1] will not return the extension if file name is like this: some.file.txt, and will fail with index out of range error if file has no extension. Always use file API, i.e. Path.GetExtension.

Also using the extension to get content type is not safe especially when pictures and videos are involved, just think of avi extension what is used by many video formats.

files.Add(Path.GetFileName(file.LocalFileName)) should be files.Add(fileName).

user3285954
  • 4,499
  • 2
  • 27
  • 19
  • @noelicus Probably you forgot that new users are not allowed to comment until they get a certain reputation, their only option is to answer. – user3285954 Jan 06 '17 at 16:51
  • Probably you forgot you can delete answers when you realise they're not relevant. :-D – noelicus Jan 09 '17 at 11:36