using FileStream to save image but image is invalid - asp.net-mvc

I'm getting an image from a base64 string, stored in a datatable. This string pulls successfully and is a valid base64 string, as I have tested it on free image decode websites and it decodes it back to the image I originally uploaded.
Now, I am trying to write the image to a file and no matter what I try, it fails to create the image file properly. The image only shows if I return it to a View as File(imageBytes, "image/jpeg")
Here is my code:
string imagepath = Path.Combine(Server.MapPath("~/Content"), client.ClientId + "_task" + task.TaskId + "_TaskReport.jpg");
byte[] imageBytes = Convert.FromBase64String(myDataTable.Rows[0].ItemArray[1].ToString()); // this works elsewhere, but for some reason only when returning the image to the view as a FileResult
using (var imageFile = new FileStream(imagepath, FileMode.Create))
{
imageFile.Write(imageBytes, 0, imageBytes.Length); // this line creates the bad image!
imageFile.Flush();
}
What is wrong with my code? Why does it work with the mvc FileResult and not when converting to an image?

Try this to write file
byte[] b= //Your Image File in bytes;
System.IO.File.WriteAllBytes(#"c:\data.jpg", b)

Try this,
[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
try
{
if (file != null && file.ContentLength > 0)
{
System.IO.MemoryStream target = new MemoryStream();
file.InputStream.CopyTo(target);
byte[] data = target.ToArray();
}
}
catch (Exception ex)
{
throw;
}
return View("Index",model);
}
return View();
}

Related

Cannot open file after downloading from Server

After downloaded a file from Server (pdf, jpg,..) successfully, I couldn't open that file in my computer.
It said "It looks like we don't support this file format". Files are stored and readable on Server.
Wonder if there is something missing in my Download Function:
[HttpGet]
public ActionResult Download(Guid? attachmentId)
{
var visitAttachment = _visitAttachmentService.FindOne(x => x.Id == attachmentId);
try
{
var serverPath = Server.MapPath(visitAttachment.Path);
byte[] fileBytes = System.IO.File.ReadAllBytes(serverPath);
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, visitAttachment.AttachmentName);
}
catch
{
return File(Encoding.UTF8.GetBytes(""), System.Net.Mime.MediaTypeNames.Application.Octet, visitAttachment.AttachmentName);
}
}
It seems like file not downloaded properly, try this, may it help, good luck
FileDownload(yourfilepath ,yourfilenamewithFormat)
{
string filename = yourfilenamewithFormat;
byte[] file_Bytes = System.IO.File.ReadAllBytes(yourfilepath);
return File(file_Bytes, System.Net.Mime.MediaTypeNames.Application.Octet, filename);
}
My opinion, is that you can be missing the file extension. If that is the case you can get it by the using Path.GetExtension(serverPath)
Edited
Try to use FileResult instead of ActionResult
[HttpGet]
public FileResult Download(Guid? attachmentId)
{
var visitAttachment = _visitAttachmentService.FindOne(x => x.Id == attachmentId);
try
{
var serverPath = Server.MapPath(visitAttachment.Path);
byte[] fileBytes = System.IO.File.ReadAllBytes(serverPath);
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, visitAttachment.AttachmentName);
}
catch
{
return File(Encoding.UTF8.GetBytes(""), System.Net.Mime.MediaTypeNames.Application.Octet, visitAttachment.AttachmentName);
}
}

Write zip files to MemoryStream

I have a controller action that creates a zip file and sends back to user for download. The problem is that the zip file gets created but it is empty. Somehow it's not writing the image files to the MemoryStream. I wonder what I am missing. If I write the zip file to the disk everything will work as expected, but I'd rather not save files to the disk if I can avoid it. This is what I have tried using dotnetzip:
public ActionResult DownloadGraphs()
{
var state = Session["State"];
using (ZipFile zip = new ZipFile())
{
if (state == "IA")
{
zip.AddFile(Server.MapPath("~/Content/DataVizByState/FallGraphs/Watermarked/Fall_IA.jpg"), "");
zip.AddFile(Server.MapPath("~/Content/DataVizByState/SpringGraphs/Watermarked/Spring_IA.jpg"), "");
}
MemoryStream output = new MemoryStream();
zip.Save(output);
output.Seek(0, SeekOrigin.Begin);
var fileName = state + "Graphs.zip";
return File(output, "application/zip", fileName);
}
}
This forces download in the view based on click of a button:
$('#graphDwnldBtn').click(function (evt) {
window.location = '#Url.Action("DownloadGraphs", "DataSharing")';
})
Do I need to use StreamWriter or Reader or something? This is the first time I have ever attempted something like this and it's been cobbled together by reading various stackoverflow posts...
Dumb mistakes: Session["State"] is an object, so the state variable was coming out as object instead of a string like I need it to be for my conditional statement to evaluate correctly. I cast state to a string to fix it. Fixed code:
public ActionResult DownloadGraphs()
{
var state = Session["State"].ToString();
using (ZipFile zip = new ZipFile())
{
if (state == "IA")
{
zip.AddFile(Server.MapPath("~/Content/DataVizByState/FallGraphs/Watermarked/Fall_IA.jpg"), "");
zip.AddFile(Server.MapPath("~/Content/DataVizByState/SpringGraphs/Watermarked/Spring_IA.jpg"), "");
}
MemoryStream output = new MemoryStream();
zip.Save(output);
output.Seek(0, SeekOrigin.Begin);
var fileName = state + "Graphs.zip";
return File(output, "application/zip", fileName);
}
}

Relevant url in file Upload

I'm uploading an image to my site using the following code,
The Image uploading just fine but, how ever
I need to fix the following things :
-I'm getting this kind of Url
C:\Users\Me\Documents\Visual Studio 2013\Projects\Wow\WowMvc5\WowMvc5\images\gallery\Picture 022.jpg,
Instead of relevant folder Url
-I thing in order to avoid an error of 2 images this the same name it would be better to create a folder under images for each image (or any better idea )
Thank you for your time
public async Task<ActionResult> Create([Bind(Include = "TakeAwayId,TakeAwayName,description,Price,DishUrl,quantity,DishesAmount,GenreId")] TakeAway takeaway)
{
var path = Server.MapPath("~/Images/gallery/");
foreach (string item in Request.Files)
{
HttpPostedFileBase file = Request.Files[item];
if (file.ContentLength == 0)
{
continue;
}
string SavedFileName = System.IO.Path.GetFileName(file.FileName);
SavedFileName = Server.MapPath
("~" + "/images/gallery/" + SavedFileName);
file.SaveAs(SavedFileName);
takeaway.DishUrl = SavedFileName;
}
if (ModelState.IsValid)
{
db.takeaway.Add(takeaway);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.GenreId = new SelectList(db.genre, "GenreId", "GenreName", takeaway.GenreId);
return View(takeaway);
}
What I would do is name and save each picture using a HashCode.
By definition, It's very improbable that 2 different strings, when transformed using a hash algorithm, will have the same output. Just to be sure, add a random string to the original name of the image.
string newName = (oldName + random).GetHashCode().ToString()
filename_1.jpg
where cnt is incremental count
if(file.exists()
{
string cnt = file.split("");
String newFileName = filename+""+(cnt+1)+".jpg";
}

ASP MVC Download Zip Files

i have a view where i put the id of the event then i can download all the images for that event.....
here's my code
[HttpPost]
public ActionResult Index(FormCollection All)
{
try
{
var context = new MyEntities();
var Im = (from p in context.Event_Photos
where p.Event_Id == 1332
select p.Event_Photo);
Response.Clear();
var downloadFileName = string.Format("YourDownload-{0}.zip", DateTime.Now.ToString("yyyy-MM-dd-HH_mm_ss"));
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "filename=" + downloadFileName);
using (ZipFile zipFile = new ZipFile())
{
zipFile.AddDirectoryByName("Files");
foreach (var userPicture in Im)
{
zipFile.AddFile(Server.MapPath(#"\") + userPicture.Remove(0, 1), "Files");
}
zipFile.Save(Response.OutputStream);
//Response.Close();
}
return View();
}
catch (Exception ex)
{
return View();
}
}
The problem is that each time i get html page to download so instead of downloading "Album.zip" i get "Album.html" any ideas???
In MVC, rather than returning a view, if you want to return a file, you can return this as an ActionResult by doing:
return File(zipFile.GetBytes(), "application/zip", downloadFileName);
// OR
return File(zipFile.GetStream(), "application/zip", downloadFileName);
Don't mess about with manually writing to the output stream if you're using MVC.
I'm not sure if you can get the bytes or the stream from the ZipFile class though. Alternatively, you might want it to write it's output to a MemoryStream and then return that:
var cd = new System.Net.Mime.ContentDisposition {
FileName = downloadFileName,
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
var memStream = new MemoryStream();
zipFile.Save(memStream);
memStream.Position = 0; // Else it will try to read starting at the end
return File(memStream, "application/zip");
And by using this, you can remove all lines in which you are doing anything with the Response. No need to Clear or AddHeader.

Check if uploaded file is an image in C# ASP.NET MVC

I have my controller
[HttpPost]
public ActionResult ChangeAvatar(HttpPostedFileBase file)
{
AvatarHelper.AvatarUpdate(file, User.Identity.Name);
return RedirectToAction("Index", "Profile");
}
And I already check if file is in jpeg/png format:
private static bool IsImage(string contentType)
{
return AllowedFormats.Any(format => contentType.EndsWith(format,
StringComparison.OrdinalIgnoreCase));
}
public static List<string> AllowedFormats
{
get { return new List<string>() {".jpg", ".png", ".jpeg"}; }
}
What I need - it ensure that uploaded file is real image file and not txt file with image extension.
I convert my uploaded file like this:
using (var image = System.Drawing.Image.FromStream(postedFile.InputStream))
{
///image stuff
}
I am thinking about try/catch block on creating image from input stream but I wonder if there is good way to do it?
Thanks)
P.S.
I wonder if there is another (more efficient way that try/catch block) way to check whether file is real image?
You could use the RawFormat property:
private static ImageFormat[] ValidFormats = new[] { ImageFormat.Jpeg, ImageFormat.Png };
public bool IsValid(Stream image)
{
try
{
using (var img = Image.FromStream(file.InputStream))
{
return ValidFormats.Contains(img.RawFormat);
}
}
catch
{
return false;
}
}
Also you could put this validation logic into a reusable validation attribute as I have shown in this post.
My solution as an extension, actually checking if a base64 string is an image or not:
public static bool IsImage(this string base64String)
{
byte[] imageBytes = Convert.FromBase64String(base64String);
var stream = new MemoryStream(imageBytes, 0, imageBytes.Length);
try
{
stream.Write(imageBytes, 0, imageBytes.Length);
System.Drawing.Image image = System.Drawing.Image.FromStream(stream, true);
return true;
}
catch (Exception)
{
return false;
}
}
Usage:
if(!"base64string".IsImage())
throw new Exception("Not an image");

Resources