I have built a website using asp.net 4.5 and MVC 5.
In one of my views I want to upload multiple files.
With my code below, the first fileis collected and saved, but it is saved as many times as the number of files I try to upload.
For example:
I choose the files pic1.jpg and pic2.jpg with the file uploader. This results in the file pic1.jpg being saved twice.
While debugging I see that the Request.Files[file]; code returns the same file each time. It seems that I get the same file uploader twice, and that only the first file is selected.
How do I alter my code to fetch all files selected via the uploader?
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ProductViewModel product)
{
...
foreach (string file in Request.Files)
{
var hpf = Request.Files[file];
if (hpf != null && hpf.ContentLength > 0)
{
var savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(hpf.FileName));
hpf.SaveAs(savedFileName);
}
}
...
return RedirectToAction<ProductController>(x => x.Index());
}
View
#model EVRY.OrderCapture.Administration.ViewModels.ProductViewModel
<h2>#Resources.Resources.Create</h2>
#using (Html.BeginForm("Create", "Product", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
...
<div class="form-group">
<label for="fileUpload" class="control-label col-md-2">Filename:</label>
<div class="col-md-10">
<input type="file" name="files" id="fileUpload" multiple />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="#Resources.Resources.Create" class="btn btn-default" />
</div>
</div>
</div>
}
I found the answer to this myself.
I had to select on index instead of name.
for (var i = 0; i < Request.Files.Count; i++)
{
var hpf = Request.Files[i];
if (hpf != null && hpf.ContentLength > 0)
{
var savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(hpf.FileName));
hpf.SaveAs(savedFileName);
}
}
Related
I want to upload image in my application without use of any JavaScript. I am new to .NET MVC development.
This is Edit View where I want to change the different image from local machine.
I am not sure whether it is possible or not. Anyone Please guide me here.
I have tried this code but file is not uploading.
#model XX.X.Models.File.ClsUpload
#Html.HiddenFor(model => model.FilePath)
<input type='file'/>
<img src=#Model.FilePath alt="Image" />
<input type="submit" value="Save" />
Using this code with .Net MVC i am saving employees pic you can try this code withOut javascript
View Code
#using (Html.BeginForm("Create", "Employees", FormMethod.Post, new { enctype =
"multipart/form-data" }))
{
<div class="row">
<div class="col-md-12">
<div class="form-group">
<input id="AttachmentName" name="AttachmentName" type="file">
</div>
</div>
</div>
}
Controller code
[HttpPost]
public ActionResult Create(EmployeeClass employeeClass, HttpPostedFileBase AttachmentName)
{
string newProfileName = "";
if (AttachmentName != null)
{
HttpPostedFileBase AttachmentNameFile = Request.Files["AttachmentName"];
string productImageExt = Path.GetExtension(AttachmentNameFile.FileName);
newProfileName = DateTime.Now.ToString("MMddyyHHmmss") + productImageExt;
var saveimage = SaveImage(AttachmentNameFile, newProfileName);
}
}
public bool SaveImage(HttpPostedFileBase AttachmentNameFile, string FileName)
{
if (AttachmentNameFile.FileName != "")
{
string folderexist = Server.MapPath("~/images/ProfileImage/");
bool isExist = System.IO.Directory.Exists(folderexist);
if (!isExist)
{
System.IO.Directory.CreateDirectory(folderexist);
}
AttachmentNameFile.SaveAs(folderexist + FileName);
}
return true;
}
I am trying to implement File Upload in MVC. I have the following code which works.
#using (Html.BeginForm("ActioName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<input type="file" name="file" />
<input type="submit" value="OK" class="button" />
</div>
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
//do something here...
}
}
Now I want to add a dropdown box (to select the file type) and send that value along with the file to my Controller. How can I do that (send other form data along with the file)?
You should be able to add them to the view, include them in the POST and have MVC take care of the model binding:
#using (Html.BeginForm("ActioName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<input type="file" name="file" />
<select name="fileType">
<option value="JPG">Photo</option>
<option value="DOC">Word</option>
</select>
<input type="submit" value="OK" class="button" />
</div>
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file, string fileType)
{
//Validate the fileType
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
//do something here...
}
}
I ended up doing it as follows it as follows. works good for me:
Created a Model:
public class FeeUpload
{
[Required (ErrorMessage="File Type required")]
public string fileType { get; set; }
[Required (ErrorMessage="file required")]
public HttpPostedFileBase File { get; set; }
}
View:
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(false, "Please fix the following:")
<div>
<div>
#Html.DropDownListFor(model => model.fileType,
new List<SelectListItem>
{
new SelectListItem{ Text="xxx", Value = "yyy" },
new SelectListItem{ Text="xxx", Value = "yyy" },
new SelectListItem{ Text="xxx", Value = "yyy" }
}, "Select")
#*#Html.ValidationMessageFor(model => model.fileType)*#
</div>
<div>
#Html.TextBoxFor(model => model.File, new { type = "file" })
#*#Html.ValidationMessageFor(model => model.File)*#
<input type="submit" value="OK" class="button" id="btnsubmit" />
</div>
</div>
}
Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult FeesAndCostsUpload(FeeUpload feeUploadFile)
{
if (ModelState.IsValid)
{
//do something with feeUploadFile.File and feeUploadFile.fileType
}
return View();
}
Try to not use Razor for the form
<form method="POST" data-url="#Url.Action("Action", "Controller")" enctype="multipart/form-data">
#Html.ValidationSummary(true)
<span class="btn btn-success fileinput-button">
<i class="fa fa-plus"></i>
<span>Add a file...</span>
#Html.TextBoxFor(model => model.Fichier, new { type = "file" })
</span>
<div class="form-group form-actions">
<div class="col-sm-offset-3 col-sm-9">
<input id="submit" type="submit" class="btn btn-primary" value='Value' />
</div>
</div>
</form>
worked for me
I have the following _CreateOrEditPartial partial view which contain a text & a file upload:-
#model TMS.Models.DataCenter
#* This partial view defines form fields that will appear when creating and editing entities *#
#Html.AntiForgeryToken()
<div>
<span class="f">Name </span>
#Html.EditorFor(model=>model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div>
<span class="f">Data Center Picture </span>
<input type="file" name="DataCenterfile" />
</div>
and the following main view :-
#using (Html.BeginForm("Create","DataCenter", FormMethod.Post))
{
#Html.ValidationSummary(true)
#Html.Partial("_CreateOrEdit", Model)
<input type="submit" value="Create" class="btn btn-primary"/>
}
Which will call the following ActionMethod:-
[HttpPost]
[ValidateAntiForgeryToken]
[CheckUserPermissions(Action = "Edit", Model = "DataCenter")]
public ActionResult Create(DataCenter dc, HttpPostedFileBase DataCenterfile)
{
// Verify that the user selected a file
if (DataCenterfile != null && DataCenterfile.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(DataCenterfile.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
DataCenterfile.SaveAs(path);
}
but the datacenterfile will always be null .. can anyone advice what is causing this problem?
Thanks
You forgot to add the enctype attribute to your form.
Something like this:
#using (Html.BeginForm("actionName", "controllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
}
About enctype attribute: What does enctype='multipart/form-data' mean?
View:
#using (Html.BeginForm("Edit","program","",FormMethod.Post,new {enctype = "multipart/form-data"}))
{
<div class="upload">
<input type="file" name="files" id="EpExpert"/>
<input type="file" name="files" id="EpNewbie"/>
<input type="submit" name="submit" value="submit" id="submit"/>
</div>
}
Controller:
[HttpPost]
public ActionResult Edit(tr_program program, IEnumerable<HttpPostedFileBase> files)
{
foreach (var file in files)
{
if (file != null)
{
//string extension = Path.GetExtension(file.FileName);
string path = AppDomain.CurrentDomain.BaseDirectory + "Documents/Program-PDFs/";
string filename = Path.GetFileName(file.FileName);
file.SaveAs(Path.Combine(path, filename));
}
}
}
uploaded file name should be in file-{id}.pdf
eg: file-EpNewbie.pdf
file-EpExpert.pdf
PLEASE help!!
The id is never sent to the server. You could use the name attribute instead:
#using (Html.BeginForm("Edit", "program", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="upload">
<input type="file" name="EpExpert" />
<input type="file" name="EpNewbie" />
<input type="submit" name="submit" value="submit" id="submit"/>
</div>
}
and in your controller action:
[HttpPost]
public ActionResult Edit(tr_program program)
{
string location = Server.MapPath("~/Documents/Program-PDFs");
foreach (string name in Request.Files)
{
HttpPostedFileBase file = Request.Files[name];
string filename = string.Format("file-{0}.pdf", name);
filename = Path.Combine(location, filename);
file.SaveAs(filename);
}
...
}
Obviously since you are storing all the files in the same location (~/Documents/Program-PDFs) with the same names (file-EpExpert.pdf and file-EpNewbie.pdf) if 2 users upload different files at the same time they might get overwritten. There seems to be a problem with your design and naming convention but in my answer I illustrated how you could pass the name of the file input to the controller action which could be used to build the resulting filename. Now it's up to you to take this into consideration when building your real application.
You can take an idea from here. Firstly declare id and data-id dynamic. for example
id = '#model.Id' data-id = '#model.Id'
Before submit form, use js or jquery take id value, then post form.
$("#myForm").submit(function () {
var idValue = $(this).attr('data-id');
document.getElementById('yourHiddenValue').value = idValue;
});
I'm trying to upload a image along with other fields. Been following examples from here and here
However it seems that the image object isn't passed to the controller and i'm unable to find any error.
Here's the view:
#model Project.Models.ContentNode
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("Create", "News", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>News</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
#*Image upload field*#
<div class="editor-field">
<input type="file" name="file" />
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Body)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Body)
#Html.ValidationMessageFor(model => model.Body)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Here are the controller methods:
public ActionResult Create()
{
var model = new ContentNode();
return View( model );
}
[HttpPost]
public ActionResult Create(ContentNode nyF, HttpPostedFileBase imageData)
{
// Get the type of content from DB
var k = (from ct in _db.ContentTypes
where ct.ID == 1
select ct).Single();
var curUser = (from u in _db.Users
where u.Username == User.Identity.Name
select u).Single();
nyF.Author = curUser;
nyF.ContentType = k;
nyF.dateCreated = DateTime.Now;
_db.ContentNodes.Add(nyF);
_db.SaveChanges();
// Process image
if ((imageData != null && imageData.ContentLength > 0))
{
var fileName = Path.GetFileName(imageData.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
imageData.SaveAs(path);
}
else
{
return Content("The image object wasn't received");
}
return View(nyF);
}
I've read over the whole thing over and over and am unable to see the error. Anyone here willing to point out what I'm doing wrong?
The name of the input file needs to match the action parameter
<input type="file" name="file" />
should be
<input type="file" name="imageData" />
or you change your action parameter name
public ActionResult Create(ContentNode nyF, HttpPostedFileBase file)
You can upload file, using Request.Files in your post method.
You can validate uploaded file using following code.
Request.Files[0].ContentLength