Searching and Retriving image from a folder - c#

hi i am doing a project in MVC4 using c#.
in my project i am storing some group of persons details in database with unique id.and also storing the profile pic of particular person in a folder in my project.(Id number and pic name is same).
in view i want display all these details.Problem is in images. I use the following codes
View
#foreach(var item in Model)
{
<td><img src="#Url.Action("ImageRetrive", "Member", new {imgname=(item.Id)})" /><br />Rtn. #item.Mem_NA<br />(#item.Mem_Occ)</td>
}
controller
public string ImageRetrive(int imgname)
{
string keyword=image.ToString();
string imagefolderpath = Server.MapPath("~/Content/Member/MemberPhotos");
string currentimage = new Member().GetImage(imagefolderpath,keyword);
string fullpath = "~/Content/Member/MemberPhotos/" + currentimage;
return fullpath;
}
model
public string GetImage(string path,string keyword)
{
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] images = di.GetFiles();
foreach (FileInfo image in images)
{
var name = image.Name;
if (name.Contains(keyword))
{
imgname = name;
}
}
return imgname;
}
But i didnot get any output. in the controller the variable fullpath is giving the link. but it can take in . Please help me.

I think you need is FilePathResult, change your controller code as
public FilePathResult ImageRetrive(int imgname)
{
string keyword=image.ToString();
string imagefolderpath = Server.MapPath("~/Content/Member/MemberPhotos");
string currentimage = new Member().GetImage(imagefolderpath,keyword);
string fullpath = "~/Content/Member/MemberPhotos/" + currentimage;
return File(fullpath, "image/png"); //Changed here
}
or You can use FileContentResult
public FileContentResult Retrive(int imgname)
{
return File(ConvertToByteArray(YourFile), "image/png"); //Changed here
}

In your view you pass imgname as parameter and in your controller you get image.
Controller
public string ImageRetrive(int imgname){ }
Change return path
return File(fullpath, "text/plain");

Related

How to retrieve list of images from GridFS?

This is to submit a view that uses ajax to pull the data.
I am trying to retrieve an image from MongoDb GridFS bucket. The download operation works. But the issue is, the view model that I use has:
public User User { get; set; }
public List<IFormFile> ImageUpload { get; set; }
I get the user from the db context, and use that to identify the image from the bucket and I want to return it to the view from the controller.
The following is my controller code:
public IActionResult AddEditUser(int id = 0)
{
if (id == 0)
{
return View(new UserImgBinder());
}
else
{
var userImageId = _context.User.Where(x => x.UserId.Equals(id)).Select(y => y.AvatarImg).ToString();
var stream = ContextNew.ImagesBucket.OpenDownloadStream(new ObjectId(userImageId.ToBson()));
var contentType = stream.FileInfo.Metadata["ContentType"].AsString;
//File(stream, contentType);
IFormFile file = new FormFile(stream, 0, stream.Length,"","");
var UserImgBinder = new UserImgBinder
{
User = _context.User.Where(x => x.UserId.Equals(id)).FirstOrDefault(),
ImageUpload = file
};
return View(UserImgBinder);
}
}
Since ImageUpload is of type List and what I am trying to feed it is not a list I am getting error.
What should I write to solve this? Is this approach bad?
Please help.
Thanks.
Try code like:
var UserImgBinder = new UserImgBinder
{
User = _context.User.Where(x => x.UserId.Equals(id)).FirstOrDefault(),
ImageUpload = new List<IFormFile> {
file
}
};

How to get actual path of a file listed in listbox?

I have a listbox which lists certain files from a certain directory.
I added a messagebox which would show me the path of the file when i click on any list item.
But when I click on any filename in the listbox, instead of showing the actual path, it shows the project file path.
Following is my code:
private void btnrecprefresh_Click(object sender, EventArgs e)
{
string[] files = Directory.GetFiles(#"C:\testt", "*.txt", SearchOption.AllDirectories);
foreach (string f in files)
{
string modelpath = Path.GetFullPath(f);
string entry = Path.GetFileName(f);
Listbox.Items.Add(entry);
}
}
private void Listbox_SelectedIndexChanged(object sender, EventArgs e)
{
string selectedItems = Listbox.SelectedItems.ToString();
string all = Path.GetFullPath(selectedItems);
MessageBox.Show(all);
}
Instead of showing the path as C:\testt\xyz.txt, it shows the path as C:\Users\Production\Desktop\Project1\bin\Release\System.Windows.Forms.ListBox+SelectedObjectCollection
Edit for abbas:
public frmMain()
{
InitializeComponent();
Listbox.DisplayMember = "Title";
Listbox.ValueMember = "Path";
}
public class FileItem
{
public string Title { get; set; }
public string Path { get; set; }
}
private void btnrecprefresh_Click(object sender, EventArgs e)
{
string[] files = Directory.GetFiles(#"C:\testt", "*.txt", SearchOption.AllDirectories);
foreach (string f in files)
{
var fileItem = new FileItem { Title = Path.GetFileName(f), Path = Path.GetFullPath(f) };
Listbox.Items.Add(fileItem);
}
}
private void Listbox_SelectedIndexChanged(object sender, EventArgs e)
{
var selectedItems = ListBox1.SelectedItems.Cast<FileItem>();
var all = string.Join(Environment.NewLine, selectedItems.Select(x => x.Path));
MessageBox.Show(all);
}
The problem:
In the following line:
string selectedItems = Listbox.SelectedItems.ToString();
All you're doing is calling the ToString on the object. Getting the path of that object will naturally give you the C:\Users\... path.
Solution:
A way of achieving what you want, is to create a class that serves as a container with the information you need:
public class FileItem
{
public string Title { get; set; }
public string Path { get; set; }
}
Then, you fill the listbox with the path and title of the file when you have read the folder:
string[] files = Directory.GetFiles(#"C:\Temp", "*.txt", SearchOption.AllDirectories);
foreach (string f in files)
{
var fileItem = new FileItem { Title = Path.GetFileName(f), Path = Path.GetFullPath(f) };
listBox1.Items.Add(fileItem);
}
In the constructor of the form, add following lines:
listBox1.DisplayMember = "Title";
listBox1.ValueMember = "Path";
The string values correspond to the properties in the FileItem class. In the changed event of the listbox, change your code to following:
var selectedItems = listBox1.SelectedItems.Cast<FileItem>();
var all = string.Join(Environment.NewLine, selectedItems.Select(x => x.Path));
MessageBox.Show(all);
This creates a string with all the paths of the files that are selected in the listbox.
Example output:
The Path.GetFullPath method returns the current directory path if only the name of file is supplied:
This method uses current directory and current volume information to
fully qualify path. If you specify a file name only in path,
GetFullPath returns the fully qualified path of the current directory.
This is the reason why in your Listbox_SelectedIndexChanged method current directory path is returned.
Instead you should save the full path of the file separately from the text of the list box items and retrieve it in your Listbox_SelectedIndexChanged method:
// btnrecprefresh_Click method
string[] files = Directory.GetFiles(#"C:\test", "*.txt", SearchOption.AllDirectories);
foreach (string f in files)
{
string entry = Path.GetFileName(f);
var item = new ListBoxItem() { Content = entry, Tag = f };
listbox.Items.Add(item);
}
// Listbox_SelectedIndexChanged method
var selectedItem = listbox.SelectedItem as ListBoxItem;
string path = selectedItem.Tag.ToString();
MessageBox.Show(path);

Add dynamic FileName to DotNetZip MVC Extension Method

I'm using the DotNetZip MVC Extension Method example for adding multiple files (I am getting mine from a repository) but I can't seem to figure out how to pass my own fileName into the extension method and get a result other than "file.zip", which is their examples hardcoded default value. Below is my CSHTML code, my Action and my Extension Method. You will see in my Action that I have a filename I want to use.
I'm embarrassed to show my attempts, but you can see what I'd like to use for my filename. Any suggestions?
CSHTML (Razor)
Download
Controller Action:
public ActionResult Download(int id)
{
var allImages = _repo.GetImagesByRender(id);
var list = new List<String>();
var render = _repo.GetRenderById(id);
var fileName = render.Select(r => r.Title);
foreach (var img in allImages)
{
list.Add(Server.MapPath("~/ImageStore/" + img.Path));
}
return new ZipResult(list);
}
The Extension Method
public class ZipResult : ActionResult
{
private IEnumerable<string> _files;
private string _fileName;
public string FileName
{
get
{
return _fileName ?? "file.zip";
}
set { _fileName = value; }
}
public ZipResult(params string[] files)
{
this._files = files;
}
public ZipResult(IEnumerable<string> files)
{
this._files = files;
}
public override void ExecuteResult(ControllerContext context)
{ // using clause guarantees that the Dispose() method is called implicitly!
using (ZipFile zf = new ZipFile())
{
zf.AddFiles(_files, false, "");
context.HttpContext.Response
.ContentType = "application/zip";
context.HttpContext.Response
.AppendHeader("content-disposition", "attachment; filename=" + FileName);
zf.Save(context.HttpContext.Response.OutputStream);
}
}
}
As for the Repo, it returns the proper Images collection associated by RenderId and also the propper Render so that I can use the Render Title as the fileName, but how would I modify the ACtion and the Extended Action Method in order to make my zipFile have the proper name?
You can add another constructor to your ZipResult class:
...
public ZipResult(IEnumerable<string> files, string fileName)
{
this._files = files;
this._fileName = fileName;
}
...
Then in controller you cne use it:
...
return new ZipResult(list, "test.zip");

Creating an instance of HttpPostedFileBase for unit testing

I need to create an instance of HttpPostedFileBase class object and pass it to a method, but I cannot find any way to instantiate it. I am creating a test case to test my fileupload method.
This is my method which takes an HttpPostedFileBase object. I need to call it from my test case class. I am not using any mock library.
Is there a simple way to do this?
[HttpPost]
public JsonResult AddVariation(HttpPostedFileBase file, string name, string comment, string description, decimal amount, string accountLineTypeID)
{
var accountLineType = _fileService.GetAccountLineType(AccountLineType.Debit);
if (Guid.Parse(accountLineTypeID) == _fileService.GetAccountLineType(AccountLineType.Credit).AccountLineTypeID)
{
amount = 0 - amount;
}
var info = new File()
{
FileID = Guid.NewGuid(),
Name = name,
Description = description,
FileName = file.FileName,
BuildID = Guid.Parse(SelectedBuildID),
MimeType = file.ContentType,
CreatedUserID = CurrentUser.UserID,
UpdatedUserID = CurrentUser.UserID,
Amount = amount,
};
var cmmnt = new Comment()
{
CommentDate = DateTime.Now,
CommentText = comment,
FileID = info.FileID,
UserID = CurrentUser.UserID
};
_variationService.AddVariation(info, file.InputStream);
_variationService.AddComment(cmmnt);
return Json("Variation Added Sucessfully", JsonRequestBehavior.AllowGet);
}
HttpPostedFileBase is an abstract class so therefore it cannot be directly instantiated.
Create a class that derives from HttpPostedFileBase and returns the values you are looking for.
class MyTestPostedFileBase : HttpPostedFileBase
{
Stream stream;
string contentType;
string fileName;
public MyTestPostedFileBase(Stream stream, string contentType, string fileName)
{
this.stream = stream;
this.contentType = contentType;
this.fileName = fileName;
}
public override int ContentLength
{
get { return (int)stream.Length; }
}
public override string ContentType
{
get { return contentType; }
}
public override string FileName
{
get { return fileName; }
}
public override Stream InputStream
{
get { return stream; }
}
public override void SaveAs(string filename)
{
throw new NotImplementedException();
}
}
I think that #BenjaminPaul has the best answer - but wanted to add this in case anyone else is looking to test the content length on the MyTestPostedFileBase object.
I created the class as is outlined above and then passing a stream that is filled with random bytes - this allows the `MyTestPostedFileBase.ContentLength to return a testable value that I needed.
byte[] byteBuffer = new Byte[10];
Random rnd = new Random();
rnd.NextBytes(byteBuffer);
System.IO.MemoryStream testStream = new System.IO.MemoryStream(byteBuffer);
and then instantiate it:
var TestImageFile = new MyTestPostedFileBase(testStream, "test/content", "test-file.png");

Why isn't my image displaying in my view?

I am storing images as byte arrays inside a SQL database.
Here is my Index method (inside the controller):
public ActionResult Index()
{
var list = db.UserProfiles.ToList();
Dictionary<int, ActionResult> picture = list.ToDictionary(item => item.CarID, item => CarPic(item.Picture));
ViewBag.CarPictures = picture;
return View(list);
}
Here is my CarPic method:
public ActionResult CarPic(byte[] imageBytes)
{
return imageBytes == null ? null : File(imageBytes, "image/jpeg");
}
Here is how I am trying to display the image inside my view:
foreach(var item in Model)
{
<img src="#ViewBag.CarPictures[item.CarID]"/>
}
This is what shows up in the web browser:
Here is a screenshot of Intellisense:
So Picture is not null, it is a byte array. The image itself is a JPEG. Here is the code I am using to convert the image to a byte array to store it in the database:
[Authorize]
[HttpPost]
public ActionResult Create(Stock stock, HttpPostedFileBase file)
{
if (file != null)
{
if (file.ContentType.Contains("image"))
{
using (var inputStream = file.InputStream)
{
var memoryStream = inputStream as MemoryStream;
if (memoryStream == null)
{
memoryStream = new MemoryStream();
inputStream.CopyTo(memoryStream);
}
var data = memoryStream.ToArray();
stock.Picture = data;
}
}
}
if (ModelState.IsValid)
{
db.UserProfiles.Add(stock);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(stock);
}
I have checked the Database and the field is indeed populated. Here is my Stock model:
[Table("Stock")]
public class Stock
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int CarID { get; set; }
public byte[] Picture { get; set; }
//etc etc
}
I am tearing my hair out here trying to work out why this isn't working, as I think I have done everything right. What am I doing wrong?
Thanks very much
You're misunderstanding the <img> tag.
<img src="..." /> allows you to display an image from a URL.
The src attribute must specify a URL that returns the actual image.
If you want to embed the image in the page, you can use a data: URI.

Categories

Resources