Jquery Fileupload - Ajax pass additional variables - c#

My project is MVC 5 c# I am using jquery.fileupload would like to know how I can pass additional values to the controller, in this case is the file description.
View:
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<input id="fileupload" type="file" name="files[]" multiple>
</span>
<input id="description" name="description" value="description" />
Script:
$(document).ready(function () {
var description = $("#description").val();
$('#fileupload').fileupload({
dataType: 'json',
url: '/Home/UploadFiles',
autoUpload: true,
done: function (e, data) {
$('.file_name').html(data.result.name);
$('.file_type').html(data.result.type);
$('.file_size').html(data.result.size);
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('.progress .progress-bar').css('width', progress + '%');
});
});
Controller:
public ContentResult UploadFiles()
{
var r = new List<UploadFilesResult>();
foreach (string file in Request.Files)
{
HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
if (hpf.ContentLength == 0)
continue;
string savedFileName = Path.Combine(Server.MapPath("~/App_Data"), Path.GetFileName(hpf.FileName));
hpf.SaveAs(savedFileName);
r.Add(new UploadFilesResult()
{
Name = hpf.FileName,
Length = hpf.ContentLength,
Type = hpf.ContentType
});
}
return Content("{\"name\":\"" + r[0].Name + "\",\"type\":\"" + r[0].Type + "\",\"size\":\"" + string.Format("{0} bytes", r[0].Length) + "\"}", "application/json");
}

You can send additional data to server using formData property.
See below:
$('#fileupload').fileupload({
formData: {
param1: 'test2',
param2: "test3",
param3: "test3"
}
});
The formData option can be used to set additional form data programmatically.

Related

.NET Core 6 Razor Ajax File Upload - NOT MVC

I'm using .NET Core 6 (not MVC though). I'm trying to upload a file using AJAX that will also allow me to show a progress bar. I had this working in a PHP solution but carrying over to C# is proving to be difficult. Hoping someone can assist me.
I can see from the console that it's posting the file and sending everything however in C# I'm a bit lost on how to receive it. No matter what I've tried it's always null. Ultimately I'll be saving it as bytes to the db but it's important to have the ability to show progress of the upload.
The HTML
<input type="file" id="uploaddoc" style="display: none;" accept=".doc, .docx, .pdf, .png, .jpg, .jpeg" />
<input type="button" value="Browse..." class="btn btn-primary" style="max-width: 150px;"
onclick="document.getElementById('uploaddoc').click();" />
<div class="progress" id="progCollapse" style="position: absolute; height: 10px;
width: 425px; margin-left: -15px; margin-top: 5px; display: none">
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar"
id="progress" style="width: 0" aria-valuenow="0" aria-valuemin="0"
aria-valuemax="100"></div></div>
The javascript
function uploadDoc() {
let file = document.getElementById("uploaddoc").files;
let data = { filename: this.value }
if (file.length > 0) {
let fileToLoad = file[0];
let fileReader = new FileReader();
$("#progCollapse").show()
document.getElementById("progress").style.width = "0%"
fileReader.onload = function (fileLoadedEvent) {
data.file = fileLoadedEvent.target.result;
$.ajax({
xhr: function () {
let xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
let percentComplete = evt.loaded / evt.total;
document.getElementById("progress").style.width = percentComplete * 100 + "%"
if (percentComplete === 1) {
$("#progCollapse").hide()
document.getElementById("progress").style.width = "0%"
}
}
}, false);
xhr.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
let percentComplete = evt.loaded / evt.total;
document.getElementById("progress").style.width = "100%"
}
}, false);
return xhr;
},
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
type: 'POST',
url: "/PageName?handler=SaveFile",
contentType: false,
processData: false,
data: { doc: fileReader.result },
success: function (data) {
}
});
};
fileReader.readAsDataURL(fileToLoad);
}
}
The C#
public OnPostSaveFile()
{
// This is where I'm stuck, what do I enter to receive the file correctly?
// I'm going to be converting it to bytes to save to the db
}
It kind of sounds like you're using Razor pages. If that is the case, try this tutorial on uploading files to Razor pages:
https://www.learnrazorpages.com/razor-pages/forms/file-upload
private IHostingEnvironment Environment;
public string Message { get; set; }
public IndexModel(IHostingEnvironment _environment)
{
Environment = _environment;
}
public void OnGet()
{
}
public void OnPostUpload(List<IFormFile> postedFiles)
{
string wwwPath = this.Environment.WebRootPath;
string contentPath = this.Environment.ContentRootPath;
string path = Path.Combine(this.Environment.WebRootPath, "Uploads");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
List<string> uploadedFiles = new List<string>();
foreach (IFormFile postedFile in postedFiles)
{
string fileName = Path.GetFileName(postedFile.FileName);
using (FileStream stream = new FileStream(Path.Combine(path, fileName), FileMode.Create))
{
postedFile.CopyTo(stream);
uploadedFiles.Add(fileName);
this.Message += string.Format("<b>{0}</b> uploaded.<br />", fileName);
}
}
}
You'll have to adjust to save the bytes wherever you need to.

Posting files and model to controller in ASP.NET Core MVC6

I'm migrating a project from ASP.NET RC1 to ASP.NET Core 1.0.
I have a view that allows users to upload one of more files, which I post using Jquery Ajax. I also serialize and post some settings within the same post.
The following all worked in RC1 (and pre-asp.net core):
Js:
$('#submit').click(function () {
var postData = $('#fields :input').serializeArray();
var fileSelect = document.getElementById('file-select');
var files = fileSelect.files;
var data = new FormData();
for (var i = 0; i < files.length; i++) {
data.append('file' + i, files[i]);
}
$.each(postData, function (key, input) {
data.append(input.name, input.value);
});
var url = '/ajax/uploadfile';
$.ajax({
url: url,
type: "POST",
contentType: false,
processData: false,
cache: false,
data: data,
success: function (result) {
alert('success');
},
error: function () {
alert('error');
}
});
});
Controller:
public IActionResult UploadFile(UploadFileModel model)
{
var result = new JsonResultData();
try
{
if (Request.Form.Files.Count > 0)
{
IFormFile file = Request.Form.Files[0];
//etc
}
}
}
So the above does not work anymore, no file uploaded and no model bound.
I managed to fix half the issues so now I can get the model to bind with the following code. However, the controller will still give me an exception on the Request.Files. I added the 'headers' property, and I used serializeObject (custom method). In the controller I added FromBody.
Js:
$('#submit').click(function () {
var postData = $('#fields :input').serializeArray();
var fileSelect = document.getElementById('file-select');
var files = fileSelect.files;
var data = new FormData();
for (var i = 0; i < files.length; i++) {
data.append('file' + i, files[i]);
}
$.each(postData, function (key, input) {
data.append(input.name, input.value);
});
var url = '/ajax/uploadfile';
$.ajax({
url: url,
type: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
processData: false,
cache: false,
data: serializeAndStingifyArray(data),
success: function (result) {
alert('success');
},
error: function () {
alert('error');
}
});
});
function serializeAndStingifyArray(array) {
var o = {};
var a = array;
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return JSON.stringify(o);
};
Controller:
[HttpPost]
public IActionResult UploadFile([FromBody]UploadFileModel model)
{
var result = new JsonResultData();
try
{
if (Request.Form.Files.Count > 0)
{
IFormFile file = Request.Form.Files[0];
//etc
}
}
}
html:
<div id="file-list">
<input type="file" name="file" class="file-select" accept="application/pdf,application">
<input type="file" name="file" class="file-select" accept="application/pdf,application" />
</div>
I started from this article which has some code that is almost the same as yours Upload Files In ASP.NET Core 1.0 (see Ajax case).
That worked for me fine on 1.0.0, so I implemented your changes and what I saw is that it failed to send the files in the request (client side issue).
This is how the payload should look like when working ok using F12 in chrome: (not sure why the file contents are hidden by chrome).
A little debugging and you are passing wrong data to data.append
The fix is in this line
$(".file-select").each(function () { data.append($(this).val(), $(this).get(0).files[0]); i++; })
Full code:
$(document).ready(function () {
$("#submit").click(function (evt) {
var data = new FormData();
i = 0;
$(".file-select").each(function () { data.append($(this).val(), $(this).get(0).files[0]); i++; })
var postData = $('#fields :input');
$.each(postData, function (key, input) {
data.append(input.name, input.value);
});
$.ajax({
type: "POST",
url: "/ajax/uploadfile", // <--- Double check this url.
contentType: false,
processData: false,
data: data,
success: function (message) {
alert(message);
},
error: function () {
alert("There was error uploading files!");
}
});
});
});
No need to use [FromBody] or serializeArray()
[HttpPost]
public IActionResult UploadFilesAjax(MyViewModel xxx )
{
This is my html, just in case:
<form method="post" enctype="multipart/form-data">
<div id="file-list">
<input type="file" name="file" class="file-select" accept="application/pdf,application">
<input type="file" name="file" class="file-select" accept="application/pdf,application" />
</div>
<div id="fields">
<input type="text" name="Email" />
</div>
<input type="button"
id="submit"
value="Upload Selected Files" />
</form>

Unable to upload multiple files

I am using ASP.NET MVC 5,jquery latest version.
I am trying to upload multiple files using jquery fileupload but I am unable to recieve multiple files.
View:
<input id="fileupload" type="file" multiple="multiple" name="files[]" >
<script type="text/javascript">
$(document).ready(function () {
$('#fileupload').fileupload({
dataType: 'json',
url: '/Media/UploadFiles',
autoUpload: true,
done: function (e, data) {
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('.progress .progress-bar').css('width', progress + '%');
});
});
</script>
Controller:
[HttpPost]
public ContentResult UploadFiles()
{
foreach (string file in Request.Files)
{ }
}
Here in Request.Files I am recieving only one file.
Your uploaded files are actually sent one by one.
You can change your serve code
[HttpPost]
public JsonResult UploadFiles()
{
IList<string> filesSaved = new List<string>();
foreach (string file in Request.Files)
{
HttpPostedFileBase hpf = Request.Files[file];
if (hpf.ContentLength > 0)
{
var fileName = hpf.FileName;
filesSaved.Add(fileName);
}
}
return Json(new {files = filesSaved}, JsonRequestBehavior.DenyGet);
}
and insert a breakpoint and you will see that the request goes through once for each file you're sending.
The problem is in your client code. There's an option in that plugin singleFileUploads which defaults to true, as you can read here.
You can change your client code setting singleFileUploads: false :
$(document).ready(function () {
$('#fileupload').fileupload({
dataType: 'json',
url: '/Media/UploadFiles',
autoUpload: true,
singleFileUploads: false,
done: function (e, data) {
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('.progress .progress-bar').css('width', progress + '%');
});
});
and everything should work as expected.

jquery function not being called by web api

I have an web api to post data in the table when data entered in html page through jquery.
The web api function is as:
public HttpResponseMessage Post(User user)
{
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, user);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = user.UserID }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
And the html page with jquery script is:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div>
<h2>All users</h2>
<ul id="users" />
</div>
<div>
<h2>Insert New User</h2>
First Name : <input type="text" id="firstName" /><br />
Last Name : <input type="text" id="lastName" /><br />
City : <input type="text" id="city" /><br />
Email : <input type="email" id="email" /><br />
Password : <input type="password" id="password" /><br />
Phone number: <input type="number" id="phone" /><br />
<input type="button" id="btnsave" value="Save" onclick="Post();" />
<p id="P1" />
</div>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script>
<script>
var uri = 'api/user';
$(document).ready(function () {
// Send an AJAX request
getuserlist();
});
function getuserlist() {
$.getJSON(uri)
.done(function (data) {
$('#users').html('');
// On success, 'data' contains a list of users.
$.each(data, function (key, item) {
// Add a list item for the user.
$('<li>', { text: formatItem(item) }).appendTo($('#users'));
});
});
}
function formatItem(item) {
return 'email:' + item.email + ' and First Name:' + item.firstName + ' and Last Name: ' + item.lastName;
}
function Post() {
jQuery.support.cors = true;
var source = {
'firstName': $('#firstName').val(),
'lastName': $('#lastName').val(),
'email': $('#email').val(),
'phone': $('#phone').val(),
'city': $('#city').val(),
'password': $('#password').val()
}
$.ajax({
type: "POST",
dataType: "json",
url: "/api/user",
data: source,
success: function (data) {
var strResult = "<table><th>Returned Message</th>";
// $.each(data, function (index, data) {
strResult += "<tr><td> " + source.email + " </td></tr>"
strResult += "</table>";
$("#divResult").html(strResult);
},
error: function (x, y, z) {
var strResult = "<table><th>Error Message</th>";
// $.each(data, function (index, data) {
strResult += "<tr><td> " + x.responseText + " </td></tr>"
strResult += "</table>";
$("#divResult").html(strResult);
// alert(x + '\n' + y + '\n' + z);
}
//success: function (data) {
// //alert(data);
// getuserlist();
// // alert(jQuery.parseJSON(data));
//},
//error: function (error) {
// jsonValue = jQuery.parseJSON(error.responseText);
// //jError('An error has occurred while saving the new part source: ' + jsonValue, { TimeShown: 3000 });
//}
});
});
</script>
</body>
</html>
when I click on the button to add anew user,the post() function is not working.
the page remains the same,no action,no error.
please help!
Thanks!
Firstly the url that you are posting to should be "/api/user/Post".
Output
There are several other JavaScript errors in the posted code that I had to fix. As other's have mentioned in the comments these errors were shown in the console. Knowing how to debug using the developer tools is invaluable and worth investing time to learn them.
Here is the updated code fixed:
<div>
<h2>All users</h2>
<ul id="users" />
</div>
<div>
<h2>Insert New User</h2>
First Name : <input type="text" id="firstName" /><br />
Last Name : <input type="text" id="lastName" /><br />
City : <input type="text" id="city" /><br />
Email : <input type="email" id="email" /><br />
Password : <input type="password" id="password" /><br />
Phone number: <input type="number" id="phone" /><br />
<input type="button" id="btnsave" value="Save" onclick="Post();" />
<p id="P1" />
</div>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script>
<script>
var uri = 'api/user';
$(document).ready(function () {
// Send an AJAX request
getuserlist();
});
function getuserlist() {
$.getJSON(uri)
.done(function (data) {
$('#users').html('');
// On success, 'data' contains a list of users.
$.each(data, function (key, item) {
// Add a list item for the user.
$('<li>', { text: formatItem(item) }).appendTo($('#users'));
});
});
}
function formatItem(item) {
return 'email:' + item.email + ' and First Name:' + item.firstName + ' and Last Name: ' + item.lastName;
}
function Post() {
jQuery.support.cors = true;
var source = {
'firstName': $('#firstName').val(),
'lastName': $('#lastName').val(),
'email': $('#email').val(),
'phone': $('#phone').val(),
'city': $('#city').val(),
'password': $('#password').val()
}
$.ajax({
type: "POST",
dataType: "json",
url: "/api/user/Post",
data: source,
success: function (data) {
var strResult = "<table><th>Returned Message</th>";
$.each(data, function (index, data) {
strResult += "<tr><td> " + source.email + " </td></tr>"
strResult += "</table>";
$("#divResult").html(strResult);
});
},
error: function (x, y, z) {
var strResult = "<table><th>Error Message</th>";
$.each(x, function (index, data) {
strResult += "<tr><td> " + x.responseText + " </td></tr>"
strResult += "</table>";
$("#divResult").html(strResult);
// alert(x + '\n' + y + '\n' + z);
});
}
//success: function (data) {
// //alert(data);
// getuserlist();
// // alert(jQuery.parseJSON(data));
//},
//error: function (error) {
// jsonValue = jQuery.parseJSON(error.responseText);
// //jError('An error has occurred while saving the new part source: ' + jsonValue, { TimeShown: 3000 });
//}
});
};
</script>
I have also made the assumption that your User object is as follows:
public class User
{
public string firstName { get; set; }
public string lastName { get; set; }
public string email { get; set; }
public string phone { get; set; }
public string city { get; set; }
public string password { get; set; }
}

how to send upload control data to jquery ajax wihout plugins

I am trying to upload file/files to server through Ajax request in MVC, but the file is always returning null in the controller, can you please suggest the way to pass the file data in the ajax request?
<form method="post" enctype="multipart/form-data">
<div>
#Html.AntiForgeryToken()
<input type="file" name="file" id="files" multiple><br>
<input type="button" value="Upload File to Server" id="submit">
</div>
</form>
<script type="text/javascript">
$("#submit").click(function () {
var formData = $('#files').val();
alert(formData);
$.ajax({
url: 'home/index',
type: 'POST',
datatype: 'json',
enctype: "multipart/form-data",
data: { file: formData },
//processData: false, // Don't process the files
//contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function (data) {
alert(data);
},
error: function () {
alert("failed");
}
});
});
</script>
[HttpPost]
[ActionName("Index")]
public ActionResult Index_Post(HttpPostedFileBase file)
{
string errormsg = string.Empty;
if (file != null)
{
// 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);
try
{
file.SaveAs(path);
errormsg = "uploaded";
return Json(fileName + errormsg);
}
catch
{
errormsg = "failed to upload";
return Json(fileName + errormsg);
}
}
}
else
{
errormsg = "No file selected";
return Json(errormsg);
}
return View();
}
}
Take normal button instead of submit button and try below code
$("#submit").click(function () {
var formData = new FormData();
var opmlFile = $('#myFile')[0];
formData.append("opmlFile", opmlFile.files[0]);
$.ajax({
url: 'home/index',
type: 'POST',
datatype: 'json',
enctype: "multipart/form-data",
data: formData ,
//processData: false, // Don't process the files
//contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function (data) {
alert(data);
},
error: function () {
alert("failed");
}
});
});
});
and controller action :-
[HttpPost]
[ActionName("Index")]
public HttpResponseMessage Index()
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
// Check if files are available
if (httpRequest.Files.Count > 0)
{
var files = new List<string>();
// interate the files and save on the server
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
postedFile.SaveAs(filePath);
files.Add(filePath);
}
// return result
result = Request.CreateResponse(HttpStatusCode.Created, files);
}
else
{
// return BadRequest (no file(s) available)
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}

Categories