Recently I started learning ASP.NET MVC 4 and I am struggling with how to add an image/bitmap object to a Model that I have and let the user pick an image from his desktop to upload, so I could save it to my database for displaying it later on my website.
In my training website i am doing a guitar selling website ,
I got a model that has Id , title , brand and price.
All i did was creating a index page to show all the GutiarDataContext from the database and a create page , but i want to make an option for the creation to choose an image and save it to the database and off course displaying it in the Index view.
I already went through some answers on the internet and here but I couldn't really understand what they were trying to explain there, so if someone could show me an example and explanation on how it works, that would be awesome!
Thanks :)
For Storing images in database :
In Asp.Net MVC we have to use HttpPostedFileBase for Uploaded files as shown below :-
Controller :
[HttpPost]
public ActionResult Upload(UploadViewModel model, HttpPostedFileBase file)
{
if (file != null)
{
int byteCount = file.ContentLength; <---Your file Size or Length
.............
.............
}
}
View :
#using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type="submit" value="OK" />
}
For displaying images from database(i m taking a hypothetical example here)
<img height="80" width="140" class="imgThumb" src="#Url.Action("LoadImg", "Image", new { id = m.ImgId })" alt="Loading..." />
public ActionResult LoadImg(int id)
{
byte[] image = null;
tblImage img = en.tblImages.FirstOrDefault(i => i.ImgId == id);
image = (byte[])img.ImgSrc;
return File(image, "image/png");
}
Controler Code
public static byte[] GetImageFromUpload()
{
HttpPostedFileBase postedFile = null;
if (HttpContext.Current.Request != null && HttpContext.Current.Request.Files.Count > 0)
postedFile = new HttpPostedFileWrapper(HttpContext.Current.Request.Files["imageUpload"]);
if (postedFile == null || postedFile.FileName == string.Empty) return null;
using (Image img = Image.FromStream(postedFile.InputStream))
{
var file = new byte[postedFile.InputStream.Length];
var reader = new BinaryReader(postedFile.InputStream);
postedFile.InputStream.Seek(0, SeekOrigin.Begin);
file = reader.ReadBytes((int)postedFile.InputStream.Length);
return file;
}
}
LoadEmployeeImageToObject() method can use to add the imege to Byte arry and parse it to server using session
public static void LoadEmployeeImageToObject(byte[] photo , int employeeId)
{
if (HttpContext.Current.Request != null)
{
byte[] uploadedImageFromFileControl = GetImageFromUpload();
bool removeImage = HttpContext.Current.Request["removeImage"] == "on";
if (HttpContext.Current.Session["AjaxPhoto"] != null)
{
photo = (byte[])HttpContext.Current.Session["AjaxPhoto"];
}
else if (uploadedImageFromFileControl != null) photo = uploadedImageFromFileControl;
else if (employeeId != 0) //load image from db
{
photo = photo;
}
}
}
if you are using this code no need to create database column for save image on database.just put a column for save picture id.using below jS script you can save image on server file system.(File path)
function uploadFile() {
var fd = new FormData();
fd.append("imageUpload", document.getElementById('imageUpload').files[0]);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);
xhr.open("POST", "/HumanResource/Employee/AjaxImageUpload");//controller path
xhr.responseType = 'blob';
xhr.send(fd);
$('#divUploadStatus').show();
}
this JS method can bind with your patial view.chtml file like this
<div id="divUploadPanel">
<label>
Upload New Image:</label>
<input type="file" id="imageUpload" name="imageUpload" onchange=" uploadFile(); " /><br />
this is the code for parent chtml file
<div class="control-group">
<label class="control-label" >Photo</label>
<div class="controls">
#Html.Partial("_EditorImagePanel", Model)
</div>
</div>
Hope this will help to you.thanks :)
Related
I am trying to make a MVC app that will let the client upload an image, convert the image to a different format (.tif in this case) and return it to the client.
The problem I'm getting is that the image is always 0kB. I can't seem to figure out the problem.
The view:
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype="multipart/form-data" }))
{
<input accept=".bmp, .gif, .jpg, .jpeg" name="file" type="file" />
<input type="submit" value="Submit" />
}
The controller action:
[HttpPost]
[ActionName("Index")]
public ActionResult UploadImages(HttpPostedFileBase file)
{
var tiffEncoder = ImageCodecInfo.GetImageEncoders()
.SingleOrDefault(dec => dec.FormatID == ImageFormat.Tiff.Guid);
Stream imgStream = new MemoryStream();
using (EncoderParameters encParams = new EncoderParameters(1))
using (Image img = Image.FromStream(file.InputStream, true, true))
{
encParams.Param[0] = new EncoderParameter(Encoder.Quality, 100);
img.Save(imgStream, tiffEncoder, encParams);
}
var result = File(imgStream, "image/tiff", "image.tif");
return result;
}
Upon debugging I clearly see that the FileStream property contains data.
imgStream needs to be rewound after writing. Set imgStream.Position = 0; before passing it into File
I am trying to create a user profile picture in a ASP MVC5 project. I have added a page that is called changepicture.cshtml and will display the current user's picture.
I have an upload function that will take a picture someone uploads like hank.jpg and rename it to that users_id.jpg.
For example:
System.Data.Entity.DynamicProxies.ApplicationUser_9C8230B38B954135385F2B0311EAC02ED8B95C4D504F8424BA3ED79B37F0AAAF.jpg
I would like to display each users individual picture in the page by grabbing there user id and adding .jpg, how would I do this?
changepicture.cshtml
#model KidRoutineLogging.Models.ChangePictureViewModel
#{
ViewBag.Title = "Change Picture";
}
<h2>#ViewBag.Title.</h2>
<h4>Your Current Picture : #Html.ViewBag.CurrentPicture</h4>
<img src="#Url.Content("~/uploads/hank.jpg")" />
<br />
<br />
#using (Html.BeginForm("", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="FileUpload1" /><br />
<input type="submit" name="Submit" id="Submit" value="Upload" />
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
HomeController.cs
public async Task<ActionResult> Index()
{
foreach (string upload in Request.Files)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/";
//string filename = Path.GetFileName(Request.Files[upload].FileName);
//Request.Files[upload].SaveAs(Path.Combine(path, filename));
Request.Files[upload].SaveAs(Path.Combine(path, user + ".jpg"));
}
return View();
}
You are getting a funky-typed name for your file because you are attempting to cast an entire class (object) to string. Additionally, if you are wanting to name the file "UserId.jpg", your code is doing more work than it should.
This line:
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
Can be simplified to this line:
var userId = User.Identity.GetUserId();
That would leave your final code as:
public async Task<ActionResult> Index()
{
foreach (string upload in Request.Files)
{
var userId = User.Identity.GetUserId();
string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/";
Request.Files[upload].SaveAs(Path.Combine(path, userId + ".jpg"));
}
return View();
}
You could get rid of the userId variable completely, and update your SaveAs method to
Request.Files[upload].SaveAs(Path.Combine(path, User.Identity.GetUserId()+ ".jpg"));
Also - you really should decorate this ActionResult with the <HttpPost> attribute since it should only be handling the POSTing of the form and not associated with a GET request.
I'm creating an app in c# mvc, where users can upload mp3 files, Below is my Upload controller:
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
string x = Request["ss"];
song std = new song();
if (file != null && file.ContentLength > 0)
try
{
// string path = Path.Combine(Server.MapPath("~/Songs"), Path.GetFileName(file.FileName));
string path = "~/Songs/" + Path.GetFileName(file.FileName);
var allowedExtensions = new[] { ".mp3",".MP3" };
var extension = Path.GetExtension(file.FileName);
if (!allowedExtensions.Contains(extension))
{
ViewBag.Message = "Only .mp3 extension files are allowed!!";
}
else
{
file.SaveAs(Server.MapPath(#"~\Songs\" + file.FileName));
//file.SaveAs(path);
string[] arr = { };
arr = (file.FileName).Split('.');
std.name = arr[0];
if (x == null || x == "")
{
std.artist = "Not Mentioned";
}
else {
std.artist = x;
}
std.likes = "0";
std.dislikes = "0";
repo4.save4(std); //call the function..
ViewBag.Message = "Song uploaded successfully!! ";
}
}
catch (Exception ex)
{
ViewBag.Message = "ERROR:" + ex.Message.ToString();
}
else
{
ViewBag.Message = "You have not specified a file.";
}
return View();
}
below is my view for index.cshtml:
#using (Html.BeginForm("index", "Upload", FormMethod.Post, new { enctype ="multipart/form-data" }))
{
<label class="l" for="file">Upload Song:</label>
<input class="l" type="file" name="file" id="file" />
<div class="form-inline form-group">
<label class="l">Artist' Name : </label>
<input type="text" class="form-control" name="ss" maxlength="30" placeholder="Leave it blank if u want.." />
</div>
<input type="submit" class="btn btn-warning" value="Upload" />
<div class="text-danger">#ViewBag.Message</div><br /><div class="text-success">Search uploaded song HERE</div>
}
Now, I'm saving the mp3 files to a folder named as Songs..this code seems to be working fine when i build my project on VS..but after deployment on app harbor, when i try to upload an mp3 file i keep getting following error:
ERROR:Access to the path
'D:\Users\apphb180c99d1921484\app_PublishedWebsites\WebMatrixWebsite\Songs\Wake
Me Up.mp3' is denied.
Please any help would be appreciated as i cant get my head around it..thanx!!
Working for me now..in case anyone's still wondering how..you need to give permissions for NETWORK SERVICE to your folder where the files are being stored..
In this case:
Songs->properties..open the security tab -> edit -> Add..
choose the Locations.. to your pc..then write "NETWORK SERVICE" under "enter the object names to select" then check names and enter ok...
now give it the permissions by selecting one of the check boxes, you might wanna choose read/write..
I chose "full control" and it's working perfectly for me..hopefully it'll work out for you guys too :) cheers..
I have some issue for my c# code for upload some file...in controller file detect null.
My html code
#using (Html.BeginForm("Index", "UploadHistory",FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="uploadFile" id="uploadFile" />
<input type="submit" value="Upload File" id="btnSubmit" />
}
and this code for my controller
[HttpPost]
public ActionResult Index(HttpPostedFileBase uploadFile)
{
// Verify that the user selected a file
if (uploadFile != null && uploadFile.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(uploadFile.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
uploadFile.SaveAs(path);
}
// redirect back to the index action to show the form once again
return RedirectToAction("Index");
}
Any ideas why my upload file detect null?? i use C# mvc 4 and razor thank you.
[SOLVED]
Just error in javascript method post.
Refer to this link
Possible copy of
In short
Use
public ActionResult Index(HttpPostedFileBase uploadFile)
Also change
<input type="file" name="file" id="file" />
to
<input type="file" name="uploadFile" id="uploadFile" />
The following should work for you:
Model
public class UploadFileModel
{
public UploadFileModel()
{
Files = new List<HttpPostedFileBase>();
}
public List<HttpPostedFileBase> Files { get; set; }
}
View
#using (Html.BeginForm("Index", "Home",FormMethod.Post, new { enctype = "multipart/form-data" }))
{
Html.TextBoxFor(m => m.Files.Files, new { type = "file", name = "Files" })
<input type="submit" value="Upload File" id="btnSubmit" />
}
Controller
[HttpPost]
public ActionResult Index(UploadFileModel model)
{
var file = model.Files[0];
return View(model);
}
Use below
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
mainly use HttpPostedFileBase in your parameter
I am not sure model binding works in this scenario. Either you need to use HttpPostedFileBase as a parameter to the controller action or you need to use Request.Files option.
Using Request.Files option.
foreach (string file in Request.Files)
{
HttpPostedFile hpf = Request.Files[file] as HttpPostedFile;
if (hpf.ContentLength == 0)
continue;
string savedFileName = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
Path.GetFileName(hpf.FileName));
hpf.SaveAs(savedFileName);
}
EDIT : Here I found a blog which uses similar scenario (Model binding). It may help you - http://cpratt.co/file-uploads-in-asp-net-mvc-with-view-models/
I have a multiple upload form and I want to check if there is any files when I launch the upload. Here is my code.
View :
#using (Html.BeginForm("Upload", "Home", FormMethod.Post,
new { enctype = "multipart/form-data"}))
{
<input name="files" type="file" multiple="multiple" />
<input type="submit" value="Upload" />
}
Controller :
[HttpPost]
public ActionResult Upload(IEnumerable<HttpPostedFileBase> files)
{
if (files.Count() > 0) Console.WriteLine(files.Count()); // display 1
if(files.Any()) Console.WriteLine(files.Any()); // display true
if (files.First() == null) Console.WriteLine("first null"); // display "first null"
return View();
}
Why my program display results like that when I submit an empty form ?
I'll probably check with JS my field, but I want to understand what is these data in my IEnumerable<HttpPostedFileBase>. Thank you.
Though i am a little late for the party but still.
I had a same issue. Found an article on asp.net they said that its by design.
http://aspnetwebstack.codeplex.com/workitem/188
This is by design because the request contains that segment which has filename="". If you don't want to have the file created, please remove that segment from the request.
I fixed it via the following way.
if (RelatedFiles.Any())
{
foreach (var file in RelatedFiles)
{
if (file != null) // here is just check for a null value.
{
byte[] uploadedFile = new byte[file.InputStream.Length];
file.InputStream.Read(uploadedFile, 0, file.ContentLength);
FileInfo fi = new FileInfo(file.FileName);
var upload = new UploadedFile
{
ContentType = file.ContentType,
Content = uploadedFile,
FileName = fi.Name,
ContentExtension = fi.Extension,
};
newIssuePaper.RelatedDocuments.Add(upload);
}
}