Filtering set of images from MongoDB - c#

I have written some codes to store image files in MongoDB. Now I want to filter and retrieve some images from the mongoDB. I want to filter out some images which has some set of characters on the image name.
For Ex: say I have stored aaaa_DEX.jpg, bbbb_DEX.jpg, cccc_BVX.jpg, dddd_OUI.jpg, eeee_DEX.jpg images in mongoDB and I want to get all the images which has the "DEX" on there names. Will it be possible with Query builder? How can I do this?
To upload I use:
public JsonResult UploadPrimaryImage(string hotelCode)
{
var db = _hoteldbObj.Instance();
var primaryImageBucket = new MongoGridFS(db, new MongoGridFSSettings() {Root = "HotelPrimaryImage"});
foreach (string httpFile in Request.Files)
{
var postedFile = Request.Files[httpFile];
if(postedFile == null)
throw new InvalidOperationException("Invalid file");
var bytes = ReadToEnd(postedFile.InputStream);
using (var c = primaryImageBucket.Create(hotelCode, new MongoGridFSCreateOptions() { ContentType = postedFile.ContentType }))
{
c.Write(bytes, 0, bytes.Length);
c.Flush();
c.Close();
}
}
return new JsonResult();
}
Thank You

Performing a .find("ABC") where ABC is your filename will handle this if querying on the full file name.
If you want to query on a substring within the file name, my suggestion would be to save the substring as part of the metadata object. See this post for an example of working with metadata.

Related

How to get the data without multiple requests to the database?

I'm trying to fetch data from the database and export the data to a csv, I can achieve that, but my concern is having code that goes to the database within a for each loop, to get the data that has a relationship with the record I have already. What is the best way to implement this to avoid trips to the database within a foreach loop?
public async Task<FileResult> FetchAllStudents(int SchoolId)
{
var studentList = await student.GetAll(SchoolId);
if (studentList != null)
{
StringBuilder sb = new();
//Append new line character.
sb.Append("\r\n");
foreach (var item in studentList )
{
//Get address of each student in the list
var studentAddress = await address.GetAddressByStudentId(item.StudentId);
var addressItem = studentAddress.Where(m => m.IsPrimary = true).FirstOrDefault();
var data = $"{addressItem.AddressLine1},{item.StudentName}";
//Append data with comma(,) separator.
sb.Append(data);
}
return File(Encoding.ASCII.GetBytes(sb.ToString()), "text/csv", "file.csv");
}
return null;
}
Sound like you want to fetch data in once and you get all the data without to query muiltple time to database. It is great to implement performance of an application. My idea as follow:
Get list of id of student.
Define a function inside the address services to such as "GetListOfStudentByIds" fetching data by list id of student. You can find out Any in Linq to working with array.
You dont need this line,
**
var addressItem = studentAddress.Where(m => m.IsPrimary = true).FirstOrDefault();
**
it makes application slower. You can add conditional while fetch data from GetListOfStudentByIds.
Thanks

How can i get image data from sql DataBase

I saved my file in the database, I want to get that file for sending mail If I wrote where the condition
public EMS_PROFILE_UPLOAD_MASTER GetHrUploadeProfile(string EnqId)
{
var x = from n in db.EMS_PROFILE_UPLOAD_MASTER
where n.ENQUIRY_CODE== EnqId
select n;
foreach(var fileData in x)
{
var _FilData = fileData.FILEDATA;
}
return x.FirstOrDefault();
}
I'm getting data but here I have multiple files in my database, how can I differentiate that file?
The fact that you have multiple files with the same ID - means you cannot use the ID as the selector. Inside your code example, it seems that there may be other meta-data from that fileData object - what is inside that to further filter or control your selection for the correct file?

Move files according to searchPattern

I have excel list with file names that I want to move from one folder to another. And I can not just copy paste the files from one folder to another since there are allot of files that do not match the excel list.
private static void CopyPaste()
{
var pstFileFolder = "C:/Users/chnikos/Desktop/Test/";
//var searchPattern = "HelloWorld.docx"+"Test.docx";
string[] test = { "HelloWorld.docx", "Test.docx" };
var soruceFolder = "C:/Users/chnikos/Desktop/CopyTest/";
// Searches the directory for *.pst
foreach (var file in Directory.GetFiles(pstFileFolder, test.ToString()))
{
// Exposes file information like Name
var theFileInfo = new FileInfo(file);
var destination = soruceFolder + theFileInfo.Name;
File.Move(file, destination);
}
}
}
I have tried several things but I still think that with a array it would be the easiest way to do it(correct me if I am wrong).
The issue that I face right now is that it can not find any files (there are files under this name.
You can enumerate the files in the directory by using Directory.EnumerateFiles and use a linq expression to check if the file is contained in you string array.
Directory.EnumerateFiles(pstFileFolder).Where (d => test.Contains(Path.GetFileName(d)));
So your foreach would look like
this
foreach (var file in Directory.EnumerateFiles(pstFileFolder).Where (d => test.Contains(Path.GetFileName(d)))
{
// Exposes file information like Name
var theFileInfo = new FileInfo(file);
var destination = soruceFolder + theFileInfo.Name;
File.Move(file, destination);
}
Actually no, this will not search the directory for pst files. Either build the path yourself using Path.Combine and then iterate over the string-array, or use your approach. With the code above, you need to update the filter, because it will not find any file when given a string[].ToString (). This should do:
Directory.GetFiles (pstFileFolder, "*.pst")
Alternatively, you can iterate over all files without a filter and compare the filenames to your string-array. For this, a List<string> would be a better way. Just iterate over the files like you're doing and then check if the List contains the file via List.Contains.
foreach (var file in Directory.GetFiles (pstFileFolder))
{
// Exposes file information like Name
var theFileInfo = new FileInfo(file);
// Here, either iterate over the string array or use a List
if (!nameList.Contains (theFileInfo.Name)) continue;
var destination = soruceFolder + theFileInfo.Name;
File.Move(file, destination);
}
I think you need this
var pstFileFolder = "C:/Users/chnikos/Desktop/Test/";
//var searchPattern = "HelloWorld.docx"+"Test.docx";
string[] test = { "HelloWorld.docx", "Test.docx" };
var soruceFolder = "C:/Users/chnikos/Desktop/CopyTest/";
// Searches the directory for *.pst
foreach (var file in test)
{
// Exposes file information like Name
var theFileInfo = new FileInfo(file);
var source = Path.Combine(soruceFolder, theFileInfo.Name);
var destination = Path.Combine(pstFileFolder, file);
if (File.Exists(source))
File.Move(file, destination);
}

Faster way to match PDF's to SQL Records

I have a C# web application that matches PDF files to records in an Azure SQL server database. Part of the PDF file name includes the record ID. I don't have all the PDFs for all the records as they come in via SFTP. Currently, I make a list of all the file names, then loop through that list, pull out the record ID, find the matching record in the database and update the record. For 2k records this takes about 10 minutes to process. I was wondering if there was a faster or better optimized way to handle this?
string us_retail_directory = ConfigurationManager.AppSettings["DFCUSretailloanDirectoryGet"];
string us_post_directory = ConfigurationManager.AppSettings["DFCUSLoanDirectoryPost"];
MoveFileRecords counts = new MoveFileRecords();
DirectoryInfo directory = new DirectoryInfo(us_retail_directory);
FileInfo[] Files = directory.GetFiles("*.pdf");
foreach (FileInfo file in Files)
{
string fileSplit = Path.GetFileNameWithoutExtension(file.Name);
string[] strings = fileSplit.Split('_');
//string loanCode = strings[1];
string loanCode = strings[1].Remove(strings[1].Length - 3);
using (LoanFileEntities db = new LoanFileEntities())
{
IQueryable<dfc_LoanRecords> query = db.Set<dfc_LoanRecords>();
dfc_LoanRecords record = query.FirstOrDefault(f => f.loan_code_string == loanCode && f.region == "US");
if (record != null)
{
record.loan_file = file.Name;
record.found_date = DateTime.Now;
db.SaveChanges();
if (!File.Exists(us_post_directory + file.Name))
{ File.Move(file.FullName, us_post_directory + file.Name); }
else
{
string now = string.Format("{0:yyyyMMdd_Hmm}", DateTime.Now);
File.Move(file.FullName, us_post_directory + "(dup" + now + ")" + file.Name);
}
counts.usRetailMove++;
counts.recordCount++;
}
else
{
counts.usRetailSkip++;
counts.recordCount++;
}
}
}
return counts;
Each database lookup has some latency whereas the actual amount of data will propably not be your biggest issue.
Therefore try to batch the requests by loading multiple records at once (even if you won't use all of the fetched records [an appropriate overhead has to be determined by testing]).
You can do this in sql with a list contains (when having a set of ids) or prefetching records according to some other appropriate mechanism (e.g. by date).
Then try to match on the prefetched records and batch the insert operations.
EDIT
In your case you may query multiple records at once using a Contains expression on loan_code_string.

Render ASP .NET MVC ActionResult to string

I'm trying to render the FileContentResult's (.png files in my case) into a base64 strings to return them into json.
I've found an interesting approach from here: http://approache.com/blog/render-any-aspnet-mvc-actionresult-to/ , that supposedly doing what i need, but when I'm trying to do something like
public async ActionResult GetUsers()
{
...
var query = from user in otherUsers
join file in allFiles on user.Profile.Id equals file.Profile.Id into usersWithFiles
from userWithFile in usersWithFiles.DefaultIfEmpty(new File(){Content = new byte[0], ContentType = "image/png"})
select new UserFriendModel { Id = user.Id, UserName = user.UserName, ProfileId = user.Profile.Id, File = File(userWithFile.Content, userWithFile.ContentType).Capture(ControllerContext) };
return Json(query.ToList(), JsonRequestBehavior.AllowGet);
}
I'm getting
System.Web.HttpException:"OutputStream is not available when a custom
TextWriter is used" thrown at result.ExecuteResult(controllerContext);
line.
You can get the file (png image) in a separate query, transform the data into text format by using your text writer, and then inject it into your data model.
Some psudo code like this:
var file = GetFileQuery();
var fileString = TextWriter.Convert(file);
var query = from user in otherUsers
join file in allFiles on user.Profile.Id equals file.Profile.Id into usersWithFiles
from userWithFile in usersWithFiles.DefaultIfEmpty(new File(){Content = new byte[0], ContentType = "image/png"})
select new UserFriendModel { Id = user.Id, UserName = user.UserName, ProfileId = user.Profile.Id, File = fileString };
Another way to do it is to use 2 different action to handle the request. First action returns all the normal data for your data model, and 2nd action only returns you the image. This way you have more flexibility with your image format, i.e. you can return it in OutputStream as PNG image (without explicit serialization/deserialization).
That's my 2 cents.
Henry

Categories

Resources