I am using ASP.NET MVC 3, I want to upload a image file using an ajax form
My Index view code is:
<% using (Ajax.BeginForm("Save","Home", new AjaxOptions() { HttpMethod = "POST", InsertionMode = InsertionMode.Replace }, new { enctype = "multipart/form-data" }))
{%>
<input type="file" /><input type ="submit" value="Submit File"/>
<% } %>
and Controller code is:
[HttpPost]
public ActionResult Save()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View("Index");
}
When I upload a file and click on the button, the ajax form is submitted, but i am getting a Request.File.Count of 0.
Default unobtrusive ajax in mvc doesn't support uploading files. You need to use hidden iframe/plugin (flash, silverlight..)/html5 or combination of those.
Some scripts that might help you:
http://valums.com/ajax-upload/
http://www.uploadify.com/
You can use the the plugins suggested by #Lukáš Novotný or else you can do the following
Create an Generic HTTP handler uploadfile.ashx
Post the data to the file(set the form action="yourpath/UploadFile.ashx"
In the handler you can read the file as
HttpPostedFile uploadedfile = context.Request.Files[0];
Here's my Action that manages the file uploads. Would work with most Ajaxy file uploaders. (I think)
public ActionResult Upload(HttpPostedFileBase uploadfile)
{
try
{
var dr405 = new DR405Service().GetDR405ById(new DR405DBContext(), DR405Profile.CurrentUser.TangiblePropertyId);
var saveLocation = Path.Combine(DR405Service.SavePath + DR405Profile.CurrentUser.TangiblePropertyId);
System.IO.Directory.CreateDirectory(saveLocation);
if ((int)uploadfile.ContentLength / 1024 <= 15000)
{
uploadfile.SaveAs(Path.Combine(saveLocation, Path.GetFileName(uploadfile.FileName)));
var file = new dr405files { TangiblePropertyId = DR405Profile.CurrentUser.TangiblePropertyId, FileName = uploadfile.FileName, UploadDate = DateTime.Now };
//dr405.dr405files.Add(file);
//c.dr405s.Add(dr405);
db.Entry(file).State = file.FileId == 0 ? EntityState.Added : EntityState.Modified;
//db.Entry(dr405).State = EntityState.Modified;
new DR405Service().Save(db);
ViewData["UploadStatus"] = String.Format("File name: {0}, {1}Kb Uploaded Successfully.", uploadfile.FileName, (int)uploadfile.ContentLength / 1024);
}
else
{
ViewData["UploadStatus"] = String.Format("File exceeds 15MB upload limit. Please reduce size and try again.", uploadfile.FileName);
}
}
catch (Exception ex)
{
ViewData.ModelState.AddModelError("_FORM", ex.ToString());
}
return View();
}
Related
My problem is:
I am uploading a excel file first. After reading the file and manipulating the data, i need to generate a csv and export the same on click of the submit button.
Below is my html/javascript code:
<div>Please upload the Excel File</div>
<form method="POST" id="fileUploadForm" enctype="multipart/form-data">
<input type="file" name="file" /><br/><br/>
<input type="submit" value="Submit" id = "defaultSubmit" />
</form>
Below is the Ajax Request:
$(document).ready(function() {
$("#defaultSubmit").click(function (event) {
//stop submit the form, we will post it manually.
event.preventDefault();
// $("#fileupload").click();
// Get form
var form = $('#fileUploadForm')[0];
// Create an FormData object
var data = new FormData(form);
$.ajax({
url : "/uploadExcelFiles",
type: "POST",
enctype: 'multipart/form-data',
data: data,
processData: false,
contentType: false,
success : function(data) {
},
error : function(data) {
}
});
return false;
});
Now Below is the java code:
#RequestMapping("/uploadExcelFiles")
public void readExcelFile(HttpServletResponse response, #RequestParam("file") MultipartFile uploadedFile) {
File file = new File(uploadedFile.getOriginalFilename());
List<EmployeeData> empData = new ArrayList<>();
empData = blAttendanceService.readFile(file);
TreeMap<Object, Object> map = blAttendanceService.calculateWorkingSecondsForEmployeeInDay(empData);
List<EmployeeChartsModel> list = new LinkedList<>();
for (Entry<Object, Object> ent : map.entrySet()) {
EmployeeChartsModel ehd = new EmployeeChartsModel();
long seconds = (long) ent.getValue();
double dailyHoursSpent = (double)seconds/3600;
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-YYYY");
System.out.println("Date::: " + sdf.format((Date)ent.getKey()) + " ::::::Hours:::: " + dailyHoursSpent);
ehd.setEmployeeDate(sdf.format((Date)ent.getKey()));
ehd.setDailyHoursSpent(dailyHoursSpent);
list.add(ehd);
}
String filename = "DailyAttendanceRecord.csv";
response.setContentType("text/csv");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + filename + "\"");
try {
StatefulBeanToCsv<EmployeeChartsModel> writer = new StatefulBeanToCsvBuilder<EmployeeChartsModel>(response.getWriter())
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withOrderedResults(false)
.build();
writer.write(list);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
EmployeeChartsModel is a class for csv Model.
I am not getting any error in the code. Just the file is not exported. Also, If i read the file manually from my location and direct hit the url of this method, the file is successfully exported. But i am unable to do so through ajax post request.
Kindly suggest the changes so as to export the csv file using this ajax post request.
I am using Java, Spring Boot, Html, Javascript in my code.
I want to allow users to choose a file to download from a drop down list. Once they have made a selection, they can click the download button. However, the file does not download correctly.
Here is the controller for generating and returning the file:
[HttpPost]
public ActionResult DownloadReport(int? id, string templateChoice)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
try
{
byte[] file = GetReport(id, templateChoice);
return File(file, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "ResumeReport.docx");
}
catch (InvalidOperationException)
{
return View();
}
}
The JavaScript function which is called upon pressing the generate report button is:
function downloadReport(InputID) {
$.ajax({
type: 'POST',
url: '#Url.Action("DownloadReport", "UserProfiles")',
data: JSON.stringify({ "ID": InputID, "TemplateChoice": $("#resumeTemplates").val() }),
contentType: 'application/json; charset=utf-8'
});
}
Opening the inspect window in chrome and going to the network tab shows the document data is received, but it does not download like a regular file.
I seemed to have found a working solution which does not reload page, does not redirect the user, and does not show any excess text in the URL upon pressing the download button. I replaced my current JavaScript function with the following:
function downloadReport(inputID) {
window.location.href = '/UserProfiles/DownloadReport/?id=' + inputID + '&template=' + $('#resumeTemplates').val();
}
And my controller now looks like:
public ActionResult DownloadReport(int? id, string template)
{
if (id == null || template == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
try
{
byte[] file = GetReport(id, template);
return File(file, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "ResumeReport.docx");
}
catch (InvalidOperationException)
{
return View();
}
}
I also added this into my RouteConfig.cs file:
routes.MapRoute(
"DownloadReport",
"{controller}/{action}/{id}/{template}",
new { controller = "UserProfiles", action = "DownloadReport", id = UrlParameter.Optional, template = UrlParameter.Optional }
);
I have a form with 3 inputs (text, image, submit button).
#using (Html.BeginForm("Save", "User", FormMethod.Post, new {Id="Form1", enctype = "multipart/form-data"}))
{
<input id="FileUploadInput" name="Image" type="file"/>
<input id="FirstName" Name="FirstName">
<input type="submit" id="inputSubmit" value="Save" />
}
Now i want to submit this form from javascript with AJAX
$("#inputSubmit").click(function (e) {
e.preventDefault();
var form = $("#Form1");
form.validate();
if (form.valid()) {
$.ajax({
url: "/User/Save",
data: form.serialize(),
type: "POST",
success: function (data) {
if (data === "") {
location.reload();
}
else {
$(".content").html(data);
$.validator.unobtrusive.parse($(".content"));
}
}
});
}
return false;
});
In my controller file i have.
public ActionResult Save(UserProfileSettings settings)
{
var image = setings.Image
var name = settings.Firstname
}
My model
public class UserProfileSettings
{
public string FirstName { get; set; }
public HttpPostedFileBase Image { get; set; }
}
The problem is that in my controller method i am getting settins.FirstName, but settings.Image is always null. I think, that with this method it is not possible to serialize image file.
try use jquery plugin muliple upload:
http://blueimp.github.io/jQuery-File-Upload/
As Darin Dimitrov suggested before, it's better to use jquery forms plugin. I have already posted this in my another answer here.
Quick Example
View
#using (Ajax.BeginForm("YourAction", "YourController", new AjaxOptions() { HttpMethod = "POST" }, new { enctype = "multipart/form-data"}))
{
#Html.AntiForgeryToken()
<input type="file" name="files"><br>
<input type="submit" value="Upload File to Server">
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public void YourAction(IEnumerable<HttpPostedFileBase> files)
{
if (files != null)
{
foreach (var file in files)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// TODO: need to define destination
var path = Path.Combine(Server.MapPath("~/Upload"), fileName);
file.SaveAs(path);
}
}
}
}
I'm trying to upload a file to my J2eE spring backend. But if I set file required then it does not recognize, so therefor i conclude that it must be the way I try to send it from the front end.
HTML definition:
<form id="filesUploadForm" action="spring/uploadFile" method="post" enctype="multipart/form-data">
<input class="std" id="file" type="file" name="choose">
</form>
Javascript: (Which is triggered from another button)
function uploadFile() {
var url = 'spring/uploadFile';
var formData = $('#filesUploadForm').serialize();
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function() {
console.log('upload complete');
};
xhr.send(formData);
}
If it is relevant: here is the Java code:
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public void uploadFile(#RequestParam(value = "file", required = false) MultipartFile multipartFile) {
String fileName = multipartFile.getOriginalFilename();
System.out.println(fileName);
}
I think you need to change the parameter name in your Java code:
#RequestParam(value = "choose", required = false)
Valums file-uploader (now called Fine Uploader) doesn't work under Internet Explorer 9 but wors fine under Chrome.
So under IE it shows the name of the file and button CANCEL and no % of uploading.
Any clue?
UPDATES:
Solution is here as well MVC Valums Ajax Uploader - IE doesn't send the stream in request.InputStream
I know this question was filed under asp.net specifically, but it came up when I searched for "valums ajax upload IE9", so I'll post my fix here in case it helps anyone like myself regardless of language:
I was returning a JSON response from the AJAX upload request with a "application/json" content header. IE9 does not know what to do with "application/json" content (but Chrome/FF/etc do).
I fixed this by making sure to return a "text/html" MIME type http header on my json response from the server.
Now IE is no longer trying to download the response! Cheers
I am unable to reproduce the issue. Here's a full working example.
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Upload(HttpPostedFileBase qqfile)
{
var uploadPath = Server.MapPath("~/app_data");
if (qqfile != null)
{
var filename = Path.Combine(uploadPath, Path.GetFileName(qqfile.FileName));
qqfile.SaveAs(filename);
return Json(new { success = true }, "text/html");
}
else
{
var filename = Request["qqfile"];
if (!string.IsNullOrEmpty(filename))
{
filename = Path.Combine(uploadPath, Path.GetFileName(filename));
using (var output = System.IO.File.Create(filename))
{
Request.InputStream.CopyTo(output);
}
return Json(new { success = true });
}
}
return Json(new { success = false });
}
}
Index.cshtml view:
<script src="#Url.Content("~/Scripts/valums/fileuploader.js")" type="text/javascript"></script>
<div id="file-uploader">
<noscript>
<p>Please enable JavaScript to use file uploader.</p>
</noscript>
</div>
<script type="text/javascript">
var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader'),
action: '#Url.Action("upload")'
});
</script>
You could also include the CSS in your Layout:
<link href="#Url.Content("~/Scripts/valums/fileuploader.css")" rel="stylesheet" type="text/css" />
It seems that is IE cache issue, if you are using Ajax & GET, add timestamp value in the get parameters for the Ajax parameters, that will do the trick like this :
$.ajax({
url : "http:'//myexampleurl.php' + '?ts=' + new Date().getTime(),
dataType: "json",
contentType: "application/json; charset=utf-8",
.
.
//more stuff
If you are using java spring
#RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody YourObject excelUplaod(#RequestHeader("X-File-Name") String filename, InputStream is) {
// chrome or firefox
}
#RequestMapping(value = "/upload", method = RequestMethod.POST,headers="content-type=multipart/*", produces = "text/html")
public #ResponseBody ResponseEntity<YourObject> uploadByMultipart(#RequestParam(value = "qqfile") MultipartFile file) {
// IE
try {
String fileName = file.getOriginalFilename();
InputStream is = file.getInputStream();
// more stuff
} catch (Exception e) {
logger.error("error reading excel file", e);
}
}