Convert HttpPostBasicFile to Image in MVC - asp.net-mvc

I get a picture by uploading and I want to convert it to image file without save it.
how can I do it?
public HttpPostedFileBase BasicPicture { get; set; }
var fileName = Path.GetFileName(BasicPicture.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
BasicPicture.SaveAs(path);
By this code I can save the picture on the server but I want convert it to image
like
Image img=(Image) BasicPicture;
but it doesn't work.

You could use the FromStream method:
using (Image img = Image.FromStream(BasicPicture.InputStream))
{
... do something with the image here
}

You can also convert HttpPostedFileBase to WebImage (which gives you more API - like method Resize):
public ActionResult SaveUploadedImage(HttpPostedFileBase file)
{
if(file != null)
{
var image = new System.Web.Helpers.WebImage(file.InputStream);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), file.FileName);
image.Save(path);
}
return View();
}

With out knowing exactly what you are doing and why i can give a full intelligent answer.
Personally i would use something like this to open an image. You have saved the image to your server, so instead of casting why not new up a new image? the end result is the same!
WebImage webImage = new WebImage(path);

Related

how to save a mvc view as a file and print the same file?

In my controller, I am rendering a view.
My Action method looks like this:
public ActionResult SomePrint(Model model)
{
//Some business action
return View("viewname",model);
}
Now my requirement is to save this view as file(may be pdf file) in my solution and send it to print and delete the file once the print is done.
Tried to use Rotativa and convert it to pdf by following
public ActionResult DownloadViewPDF()
{
var model = new GeneratePDFModel();
//Code to get content
return new Rotativa.ViewAsPdf("GeneratePDF", model){FileName = "TestViewAsPdf.pdf"}
}
But i need it to save it as pdf and print the same.
Any help? Thanks in advance.
If you would have been requesting to export to a known convertible type (such as Excel), formatting the stream would be enough. But if you would like to Export to PDF you should create another View to Export the file and use a 3rd party application such as iText.
You can use BuildPdf method on ViewAsPdf.
public ActionResult DownloadViewPDF()
{
var model = new GeneratePDFModel();
var pdfResult = new ViewAsPdf("GeneratePDF", model)
{ FileName = "TestViewAsPdf.pdf" };
var binary = pdfResult.BuildPdf(this.ControllerContext);
// you can save the binary pdf now
return File(binary, "application/pdf");
}

How do I write FileContentResult on disk?

I am trying to use the Rotativa component to store (not to show) a copy of the invoice permanently on web server disk. Two questions:
Why I need to specify a controller action? ("Index", in this
case)
How do I write the FileContentResult on local disk without
displaying it?
Thanks.
Here is my code:
[HttpPost]
public ActionResult ValidationDone(FormCollection formCollection, int orderId, bool fromOrderDetails)
{
Order orderValidated = context.Orders.Single(no => no.orderID == orderId);
CommonUtils.SendInvoiceMail(orderValidated.customerID , orderValidated.orderID);
var filePath = Path.Combine(Server.MapPath("/Temp"), orderValidated.invoiceID + ".pdf");
var pdfResult = new ActionAsPdf("Index", new { name = orderValidated.invoiceID }) { FileName = filePath };
var binary = pdfResult.BuildPdf(ControllerContext);
FileContentResult fcr = File(binary, "application/pdf");
// how do I save 'fcr' on disk?
}
You do not need the FileContentResult to create a file. You've got the byte array which can be saved directly to the disk:
var binary = pdfResult.BuildPdf(ControllerContext);
System.IO.File.WriteAllBytes(#"c:\foobar.pdf", binary);
string FileName="YOUR FILE NAME";
//first give a name to file
string Path=Server.MapPath("YourPath in solution"+Filename+".Pdf")
//Give your path and file extention. both are required.
binary[]= YOUR DATA
//Describe your data to be save as file.
System.IO.File.WriteAllBytes(Path, binary);
Thats simple...

Image won't display MVC5

Hello evryone (im using MVC5),
i generate image from Chart in Html Helper Extension
public static string GetUrlFromChart(this HtmlHelper helper, Chart chart)
{
lock (obj)
{
string path = HttpContext.Current.Server.MapPath("~/App_Data/graphs/");
string filename = path + Guid.NewGuid() + ".jpg";
chart.ToWebImage("jpg").Save(filename);
return filename;
}
}
by viewmodel i send data to view and i tried to show them to user.
<img src="#Html.GetUrlFromChart(#Model.my_chart)" width="400" height="250"/>
Image generate properly, in correct path, but application cannot show me it,
its only white rectangle
when i copy image source to windows explorer.
i get that image.
but it seems to wont work with
<img></img>
anyone know how to display System.Web.Helpers.Chart like image, or display data like chart ?
Hello mate you should return the image rather than the file path
I don't know about this Chart object so I just change the code to a generic one
change your code to:
public static ActionResult GetUrlFromChart()
{
lock (obj)
{
string path = HttpContext.Current.Server.MapPath("~/App_Data/graphs/");
string filename = path + Guid.NewGuid() + ".jpg";
var image = chart.ToWebImage("jpg");
//save your image.
return File(image.GetBytes(), "image/jpeg");
}
}
in the view:
<img src="#Url.Action("GetUrlFromChart", "Yourcontrollername")"/>

ASP.NET MVC 3 Preview Image

I'm using MVC 3 and using the AjaxUpload plugin to upload an image using AJAX. I don't want to save the image in the file system, instead save it to the session object and then output the stream to populate an image control on the form? Would anyone know how to do this?
No idea why would ever want to do that (store the file in session) because if you have lots of users uploading their files at the same time, storing those files in the memory of your web server, especially if those files are big, won't make this server last very long. Storing the file on the filesystem is the recommended approach.
But anyway, here's how you could do it (assuming you didn't read or cared about my previous remark):
[HttpPost]
public ActionResult Upload(MyViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var buffer = new byte[model.File.InputStream];
model.File.InputStream.Read(buffer, 0, buffer.Length);
Session["uploadedFile"] = buffer;
return View(model);
}
where the File property on the view models is a HttpPostedFileBase. Next you could have a controller action which will serve this file:
public ActionResult Image()
{
byte[] buffer = (byte[])Session["uploadedFile"];
return File(buffer, "image/png");
}
and in the view you will have an <img> tag pointing to this action:
<img src="#Url.Action("image")" alt="" />
Now of course the AjaxUpload plugin allows you to upload the file using AJAX, so you don't need to reload the entire page. So in this case your controller action could simply return a JSON object to indicate whether the upload process succeeded and then in the success callback set the src property of the <img> tag to the controller action that will serve the file.
SomeView.cshtml:
<img src="#Url.Action("/Image/Render")" />
ImageController.cs:
public ActionResult Render() {
return File((byte[])Session["Avatar"], "image/jpeg")
}
Some example code. Modify it to whatever you want to do. Not really a good idea to sling an image into a session if lots of users. Better to stick it into a db if short lived, or if long lived, a more permanent storage (filesystem maybe).
public ActionResult UploadImage()
{
foreach (string imageName in Request.Files)
{
HttpPostedFileBase file = Request.Files[imageName];
if (file.ContentLength > 0)
{
BinaryReader br = new BinaryReader(file.InputStream);
byte[] content = br.ReadBytes(file.ContentLength);
Session[imageName] = content; // better to store in a db here
}
}
return View();
}
// return the image (controller action) /mycontroller/ViewImage?imageName=whatever
public FileStreamResult ViewImage(string imageName)
{
byte[] content = (byte[])Session[imageName] ; // where ever your content is stored (ideally something other than session)
MemoryStream ms = new MemoryStream(content);
return new FileStreamResult(ms, "application/octet-stream"); // set content type based on input image, it might be png, jpg, gif etc.,
}
Hope this helps.

ASP.NET MVC Dynamically generated image URLs

I have an ASP.NET MVC application where I am displaying images.
These images could be located on the file system or inside a database. This is fine as I can use Url.Action in my image, call the action on my controller and return the image from the relevant location.
However, I want to be able to support images stored in Amazon S3. In this case, I don't want my controller action to return the image, it should instead generate an image URL for Amazon S3.
Although I could just perform this logic inside my view e.g.
<%if (Model.Images[0].ImageLocation == ImageLocation.AmazonS3) {%>
// render amazon image
I need to ensure that the image exists first.
Essentially I need to pass a size value to my controller so that I can check that the image exists in that size (whether it be in the database, file system or amazon s3). Once I am sure that the image exists, then I return the URL to it.
Hope that makes sense,
Ben
Try the following approach.
A model class for an image tag.
public class ImageModel
{
public String Source { get; set; }
public String Title { get; set; }
}
Helper
public static String Image(this HtmlHelper helper, String source, String title)
{
var builder = new TagBuilder("img");
builder.MergeAttribute("src", source);
builder.MergeAttribute("title", title);
return builder.ToString();
}
View with Model.Images of type IEnumerable<ImageModel>
...
<%= Html.Image(Model.Images[0].Source, Model.Images[0].Title) %>
Action
public ActionResult ActionName(/*whatever*/)
{
// ...
var model = ...;
//...
var model0 = ImageModel();
if (Image0.ImageLocation == ImageLocation.AmazonS3)
model0.Source = "an amazon url";
else
model0.Source = Url.Action("GetImageFromDatabaseOrFileSystem", "MyController", new { Id = Image0.Id });
model0.Title = "some title";
model.Images.Add(model0);
// ...
return View(model);
}
An action is a kind of a pseudo code, however the idea should be clear.
After several iterations I have come up with a workable solution, although I'm still not convinced its the best solution.
Originally I followed Anton's suggestion and just set the image url accordingly within my controller action. This was simple enough with the following code:
products.ForEach(p =>
{
p.Images[0].Url = _mediaService.GetImageUrl(p.Images[0], 200);
});
However, I soon found that this approach did not give me the flexibility I needed. Often I will need to display images of different sizes and I don't want to use properties of my model for this such as Product.FullSizeImageUrl, Product.ThumbnailImageUrl.
As far as "Product" is concerned it only knows about the images that were originally uploaded. It doesn't need to know about how we manipulate and display them, or whether we are caching them in Amazon S3.
In web forms I might use a user control to display product details and then use a repeater control to display images, setting the image urls programatically in code behind.
I found that the use of RenderAction in ASP.NET MVC gave me similar flexibility:
Controller Action:
[ChildActionOnly]
public ActionResult CatalogImage(CatalogImage image, int targetSize)
{
image.Url = _mediaService.GetImageUrl(image, targetSize);
return PartialView(image);
}
Media Service:
public MediaCacheLocation CacheLocation { get; set; }
public string GetImageUrl(CatalogImage image, int targetSize)
{
string imageUrl;
// check image exists
// if not exist, load original image from store (fs or db)
// resize and cache to relevant cache location
switch (this.CacheLocation) {
case MediaCacheLocation.FileSystem:
imageUrl = GetFileSystemImageUrl(image, targetSize);
break;
case MediaCacheLocation.AmazonS3:
imageUrl = GetAmazonS3ImageUrl(image, targetSize);
break;
default:
imageUrl = GetDefaultImageUrl();
break;
}
return imageUrl;
}
Html helper:
public static void RenderCatalogImage(this HtmlHelper helper, CatalogImage src, int size) {
helper.RenderAction("CatalogImage", "Catalog", new { image = src, targetSize = size });
}
Usage:
<%Html.RenderCatalogImage(Model.Images[0], 200); %>
This now gives me the flexibility I require and will support both caching the resized images to disk or saving to Amazon S3.
Could do with some url utility methods to ensure that the generated image URL supports SSL / virtual folders - I am currently using VirtualPathUtility.
Thanks
Ben
You can create a HttpWebRequest to load the image. Check the header in the response, if it's 200 that means it was successful, otherwise something went wrong.

Resources