how to update(edit) upload files in asp.net mvc4 - c#

I want make form edit for my upload files, so I want the file delete after the new file uploaded
this for my RazorView
#model updownload.Models.updown
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.HiddenFor(x => x.id)
<div class="container">
<div>
#Html.ValidationMessage("uploadError")
#Html.TextBoxFor(x => x.upload, new { type = "file", id = "file" })
</div>
<div class="form-group">
<label>Username:</label>
#Html.TextBoxFor(x => x.keterangan)
</div>
<div class="button">
<button>Submit</button>
</div>
</div>
}
and this for my Edit controller
[HttpPost]
public ActionResult Edit(updown viewModel, HttpPostedFileBase file)
{
var currentupdown = db.updowns.Find(viewModel.id);
if (viewModel.upload != null)
{
System.IO.File.Delete(Path.Combine(Server.MapPath("~/App_Data/upload"), viewModel.upload));
string fileName = Guid.NewGuid() + Path.GetFileName(file.FileName);
string path = Path.Combine(Server.MapPath("~/App_Data/upload"), fileName);
file.SaveAs(path);
viewModel.upload = fileName;
}
else
{
currentupdown.upload = currentupdown.upload;
}
currentupdown.keterangan = viewModel.keterangan;
db.SaveChanges();
return RedirectToAction("List", "Home");
}
I got error in this line string fileName = Guid.NewGuid() + Path.GetFileName(file.FileName);
can someone fix my code please.
sorry for my bad english

You are getting a typical null reference exception because file is NULL and you are trying to access the FileName property on that.
Why is file null ?
For file upload to work from a form, the form should have enctype attribute with value set to "multipart/form-data". Your current view code will generate the form tag without that.
<form action="/Home/Edit" method="post">
</form>
So first fix that.Also, for the file uploading to work, your file input element's name attribute value must match with the name of your HttpPostedFileBase parameter.
#using (Html.BeginForm("Edit", "Home", FormMethod.Post,
new { enctype = "multipart/form-data"}))
{
#Html.LabelFor(a => a.keterangan)
#Html.TextBoxFor(a => a.keterangan)
#Html.HiddenFor(x => x.id)
<input type="file" name="file"/>
<input value="submit" type="submit" class="btn" />
}
This will render the correct HTML markup needed to send the file.
Now in the server action method, you need to d a null check on the file parameter before trying to access that.
[HttpPost]
public ActionResult Edit(updown viewModel, HttpPostedFileBase file)
{
var currentupdown = db.updowns.Find(viewModel.id);
if (file != null)
{
var location=Server.MapPath("~/App_Data/upload");
//Delete existing file
if (!string.IsNullOrEmpty(currentupdown.upload))
{
var existingFile= Path.Combine(location, currentupdown.upload);
if (System.IO.File.Exists(existingFile))
{
System.IO.File.Delete(existingFile);
}
}
var fileName = Guid.NewGuid() + Path.GetFileName(file.FileName);
var path = Path.Combine(location, fileName);
file.SaveAs(path);
currentupdown.upload = fileName; // Update to the new file name
}
currentupdown.keterangan = viewModel.keterangan;
db.SaveChanges();
return RedirectToAction("List", "Home");
}
Since you have a view model, you can also add a new property to the viewmodel called File (of type HttpPostedFileBase) and simply use that in your server action. With this you can remove the second parameter as your view model already has a property for this. So instead of checking if(file!=null), you would be doing if(viewmodel.File!=null)
public class YourViewModel
{
public int Id { set;get;}
public string Keterangan { set;get;}
public HttpPostedFileBase File { set;get;}
}
and
[HttpPost]
public ActionResult Edit(YourViewModel viewModel)
{
// use viewModel.File as needed
}

Related

#Html.ActionLink from PartialView not finding my controller action

Im trying to create an actionlink to download a file. I get the values of noticiaId and filename in the view but not in the controller.
There's something wrong with the actionlink HTML helper that Im missing.
If I do it this way:
#Html.ActionLink("Download", "DownloadAnexo", "NoticiasController", new { noticiaid = Model.ID, filename = f.File }, null)
I get HTTP 404 with this URL: localhost:port/NoticiasController/DownloadAnexo?noticiaid=55&filename=file.png
This looks correct to me but still Im getting 404 errors saying that the route was not found.
Partial View:
#model Web.Models.Noticias.NoticiaVM
<div class="col">
<label>Anexos:</label>
<table>
#if (Model.Anexos != null)
{
foreach (var f in Model.Anexos)
{
<tr>
<td>#f.File</td>
<td>
#Html.ActionLink("Download", "DownloadAnexo", "NoticiasController", new { noticiaid = Model.ID, filename = f.File }, null)
</td>
</tr>
}
}
</table>
</div>
Controller Action:
public ActionResult DownloadAnexo(int? noticiaid, string filename)
{
if(noticiaid != null && !String.IsNullOrEmpty(filename))
{
string fullPath = ConfigurationManager.AppSettings["NoticiasFiles"] + "/N_" + noticiaid + "/Anexos/";
byte[] fileBytes = System.IO.File.ReadAllBytes(fullPath);
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, filename);
}
else
return Content("");
}
I've also tried this:
<a href="#Url.Action("DownloadAnexo", "NoticiasController",
new { noticiaId = Model.ID, filename = f.File })">
Download
</a>
But i got the same result.
I'm don't have much experience with partialviews, so I'm wondering if just because im sending data from a partial directly to the controller that might not be possible or something. IDK.
Please Help.
you have a typo, NoticiasController should be Noticias
#Html.ActionLink("Download", "DownloadAnexo", "Noticias", new { noticiaid = Model.ID, filename = f.File }, null)
and fix action too
public ActionResult DownloadAnexo([FromQuery] int? noticiaid, [FromQuery]string filename)

Upload Image ASP.NET MVC

Hey I want to upload picture and save that picture to a folder, and save the name of that picture to DB in addition I am also using model binding for other fields of form. Here is the code in this HttpPostedFileBase file receives null I am also using enctype = "multipart/form-data" in my form.
public ActionResult UmrahPackage(PackagesModel model, , HttpPostedFileBase file)
{
try
{
if (model.ID == 0)
{
String fileName = "";
Pakage pkg = new Pakage();
pkg.Title = model.Title;
pkg.PackageDetail = model.PackageDetail;
pkg.Duration = model.Duration;
if (file != null)
{
fileName = System.Guid.NewGuid().ToString() + System.IO.Path.GetExtension(file.FileName);
string physicalPath = Server.MapPath("~/Images/Uploads" + fileName);
// save image in folder
file.SaveAs(physicalPath);
}}
In addition I am also trying this but I am not be able to understand that how to save image in folder I mean the object instance before SaveAs -> file
if (Request.Files.Count > 0 && String.IsNullOrEmpty(Request.Files[0].FileName) == false)
{
HttpPostedFileBase file;
fileName = System.Guid.NewGuid().ToString() + System.IO.Path.GetExtension(Request.Files[0].FileName);
string physicalPath = Server.MapPath("/uploads/profileimages/") + fileName;
file.SaveAs(physicalPath);
}
My form looks like,
#using (Html.BeginForm("UmrahPackage", "Home", FormMethod.Post, new { enctype = "multipart/form-data"}))
{
#Html.HiddenFor(model => model.ID)
<label>Title:</label>
#Html.TextBoxFor(model => model.Title)
<label>Upload Image</label>
<input type="file" id="imgInp">
<button type="submit" >Create</button>
}
Kindly help me, Thanks.
Your input element name attribute value should match with your parameter name
Since your HttpPostedFileBase parameter name is file, give the same name for your file input.
<input type="file" name="file" />
Now when the form is submitted, model binder will be able to map your submitted form data to your parameter named file
I also suggest you to use Path.Combine instead of string concatenation.
string physicalPath = Path.Combine(Server.MapPath("~/Images/Uploads"), fileName);
I had referred to this link to fix the problem of overwriting previously selected files. But this method has led to another problem. The pictures selected were duplicated. Meaning that if I choose 3 pictures, it would save 6.
The following code is my javascript
<input type="file" id="files" name="files" class="btn" style="color:white" multiple />
function previewImages() {
linebreak = document.createElement("br");
var preview = document.querySelector('#preview');
if (this.files) {
[].forEach.call(this.files, readAndPreview);
}
function readAndPreview(file) {
// Make sure `file.name` matches our extensions criteria
if (!/\.(jpe?g|png|gif)$/i.test(file.name)) {
$('#files').val('');
return alert(file.name + " is not an image");
} else if (file.size > 4194304) {
$('#files').val('');
return alert(file.name + "is larger than 4MB");
} else {
var reader = new FileReader();
reader.addEventListener("load", function () {
var image = new Image();
image.height = 100;
image.title = file.name;
image.src = this.result;
preview.append(image.title);
preview.appendChild(image);
});
reader.readAsDataURL(file);
}
}
}
//document.querySelector('#files').addEventListener("change", previewImages);
$(document).on('change', 'input[type="file"][multiple]', function () {
var $this = $(this);
$this.clone().insertAfter($this);
$this.hide();
});
$(document).on('change', 'input[type="file"][multiple]', previewImages);

Upload pdf file

I want to upload Pdf file into my application
So I have ViewModel (I post only relevant code)
public class SubcategoryViewModel
{
public HttpPostedFileBase PdfFile { get; set; }
[DisplayName("PDF")]
public string Pdf { get; set; }
}
Controller:
public async Task<string> CreateSubcategory(SubcategoryViewModel model)
{
string pdf = null;
if (model.Pdf != null)
{
pdf = Guid.NewGuid().ToString().Substring(0, 13) + "_" + model.File.FileName;
model.Pdf = pdf;
var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Content/pdf"), pdf);
model.File.SaveAs(path);
}
var subcategory = new Subcategory
{
Pdf = pdf,
};
db.SubcategoriesList.Add(subcategory);
await db.SaveChangesAsync();
View:
#model Models.ViewModels.SubcategoryViewModel
#using (Html.BeginForm("Create", "Subcategory", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
#Html.LabelFor(model => model.Pdf, new { #class = "control-label col-md-2" })
<div class="col-md-10 legend-size">
<input type="file" id="file" name="file" />
</div>
</div>
When I action post I don´t received nothing into model.Pdf, so into if (model.Pdf != null) validation it comes null, and I don´t know why
Anyone have idea why it occurs? Thankyou in advance!
You have 2 main issues. First the name of your file input is name="file", but that does not match the property in your model. It needs to be
<input type="file" name="PdfFile" />
Second, you never generate an input for property string Pdf so in the POST method, it will always be null and therefore the code inside your if (model.Pdf != null) will never be executed. However, what you really want is to save the file if its not null, so the code needs to be
public async Task<string> CreateSubcategory(SubcategoryViewModel model)
{
string fileName = null;
if (model.PdfFile != null && model.PdfFile .ContentLength > 0)
{
fileName = Guid.NewGuid().ToString().Substring(0, 13) + "_" + model.PdfFile.FileName;
string path = Path.Combine(HttpContext.Current.Server.MapPath("~/Content/pdf"), fileName);
model.PdfFile.SaveAs(path);
}
var subcategory = new Subcategory
{
Pdf = fileName ,
};
db.SubcategoriesList.Add(subcategory);
await db.SaveChangesAsync();
Side note: I would also recommend an additional property in your model for the files display name (i.e. the value of model.PdfFile.FileName) so that you can use that in your view rather than displaying the name prefixed with a Guid which would have little meaning to the user. Refer this answer for an example.
I think your problem is you are getting null value in PdfFile property of your model. This is because you have not given name attribute of file upload control same as you property. change name attribute of your file upload control to PdfFile.
<input type="file" id="file" name="PdfFile" />

How to upload image with custom name with it's original extension?

I'm trying to upload images in a form which I basically have done already, but I want the image to be named specifically for each user who registers.
For example, each email will be unique, if there is another email already in the database then the form will return false (it will not let him/her register).
So what I did was change the file name to the email he/she typed in the form.
But now the file will not have it's original extension (.jpg .png etc).
Is there a way I could pull the file original extension?
Here's what I have in my controller:
[HttpPost]
public AcitonResult Register(Registration signingUp, HttpPostedFileBase avatar)
{
var db = new AvatarDBEntities();
if (ModelState.IsValid)
{
var FindEmail = db.tblProfiles.FirstOrDefault(e => e.PROF_Email == signingUp.Email);
if (FindEmail == null)
{
var Data = db.tblProfiles.Create();
Data.PROF_Email = signingUp.Email;
if (avatar != null)
{
string profpic = System.IO.Path.GetFileName(avatar.FileName);
string profpic_name = signingUp.Email + ".jpg"; //this is what I'm trying to change
string path = System.IO.Path.Combine(Server.MapPath("~/assets/images/user_images/avatars"), profpic_name);
avatar.SaveAs(path);
}
db.tblProfiles.Add(Data);
db.SaveChanges();
}
else
{
ModelState.AddModelError("Email", "That Email already exist.");
return View();
}
}
return View();
}
View:
#using (Html.BeginForm("Register", "Main", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.TextBoxFor(r => r.Email, new { #class = "custom-input Email" })<br/>
#Html.ValidationMessageFor(a => a.Email)<br/>
<label for="avatar">Profile picture:<span class="required">*</span></label><br />
<input type="file" name="avatar" id="avatar" /><br/>
<input type="submit" />
}
The image is in the folder with the name as their email and the extension of .jpg.
I just want to pull the extension of the original file and add it after it pulls the email value.
Thanks.
What I think you're looking for is
Path.GetExtension(string fileName)
So your code becomes
string profpic_name = signingUp.Email + Path.GetExtension(avatar.FileName);
There is a method called Path.GetExtension
Store the extension in a temp variable first, then use it later.
string tempExtension = Path.GetExtension(avatar.FileName);

ASP.net MVC upload image NullReferenceException

I've implemented simple create method to put data in database, and it worked fine. I've decided to add image upload, but I keep getting NullReferenceException (file is null) and I can't figure out why.
I hope you can help me!
Here's my code:
[Authorize]
public ActionResult Create()
{
ViewBag.CategoryId = new SelectList(_categoryRepository.GetAllCategories().AsEnumerable(), "CategoryId",
"Name");
return View();
}
//
// POST: /Advert/Create
[HttpPost, Authorize]
public ActionResult Create(CompetitionDTO competitionDTO, HttpPostedFileBase file)
{
if (file.ContentLength > 0)
{
string fileName = Path.GetFileName(file.FileName);
string fileExtension = Path.GetExtension(fileName);
if ((fileExtension == ".jpg") || (fileExtension == ".png"))
{
string path = Path.Combine(Server.MapPath("~/Uploads/Images"), fileName);
file.SaveAs(path);
competitionDTO.ImageURL = path;
}
}
if (ModelState.IsValid)
{
_competitionRepository.AddCompetition(competitionDTO, WebSecurity.CurrentUserId);
return RedirectToAction("Index");
}
ViewBag.CompetitionId = new SelectList(_competitionRepository.GetAllCompetitions().AsEnumerable(),
"CompetitionId", "Name");
return View(competitionDTO);
}
}
and View
<div>
#using (Html.BeginForm("Create", "Competition", FormMethod.Post, new
{
enctype = "multipart/form-data"
, id = "parentForm"
}))
{
<input type="file" name="file" id="file"/>
<input type="submit" value="Create" />
}
</div>
EDIT
I if I wasn't clear enough:
I know how to insert data to database and I know how to upload file, and I want when I click submit that those 2 things happen at same time
It was my mistake I had two Html.BeginForms, now I merged them into one and it works fine

Categories

Resources