File upload using ajax request - c#

I am trying to upload image, using ajax. i am sending request like this:
#using (Ajax.BeginForm("SaveReferral", "ReferralIM", new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "OnSuccessReferralSent"
}, new { id = "frmReferral", onSubmit = "OnControlMapping(this);" }))
{
}
if i send request like this:
#using (Html.BeginForm("SaveReferral", "ReferralIM", FormMethod.Post, new { id = "frmReferral", enctype = "multipart/form-data" }))
{
File uploaded successfully, but i want to use ajax ,Please help me how i should do for file uploading with ajax.
Thanks

I am not using MVC BUT if you want to use $.ajax then here it is...
$('.file-uploadID').on('click', function (e) {
e.preventDefault();
var fileInput = $('.file-uploadID');
var fileData = fileInput.prop("files")[0]; // Getting the properties of file from file field
formData.append("file", fileData); // Appending parameter named file with properties of file_field to form_data
formData.append("user_email", email); //adding email address as parameter if you have
$.ajax({
url: '/FileUploadHandler.ashx',
data: formData,
processData: formData.processData,
contentType: formData.contentType,
type: 'POST',
success: function (data) {
var obj = $.parseJSON(data);
if (obj.StatusCode == "OK") {
alert("file upload done");
} else if (obj.StatusCode == "ERROR") {
alert("file upload error");
}
},
error: function (errorData) {
$('.result-message').html("There was a problem uploading the file. Please try again.").show();
}
});
});
Handler
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Expires = -1;
var email = context.Request.Params["user_email"];
var fileData = context.Request.Files["file"];
try
{
var result = UploadImageToServer(email, fileData);
context.Response.Write(result);
}
catch (Exception ex)
{
context.Response.Write("error while uploading file to the server, please try again.");
}
}

Related

How to send a file data to controller method with angularjs?

My project is Asp.net MVC Core.
I try to upload a file with angularjs to mvc controller but i make some mistakes; sending value is null in method. I can write a console log , actually data is not null but problem is sending to the controller.
angular.module("myApp").controller("myVm", function ($scope, $http, $window) {
var vm = $scope;
var url = "UploadSingle";
var config = {
headers: {
"Content-Type": undefined,
}
};
vm.upload = function () {
var formData = new $window.FormData();
formData.append("file-0", vm.files[0]);
console.dir(formData);
$http.post(url, formData, {
transformRequest: angular.identity,
headers: new HttpHeaders().set('enctype', 'multipart/form-data')
}).
then(function (response) {
vm.result = "SUCCESS";
vm.data = response.data.data;
}).catch(function (response) {
vm.result = "ERROR " + response.status;
});
};
public async Task<JsonResult> UploadSingle(IFormFile formData)
{
using (var reader = new StreamReader(formData.OpenReadStream()))
{
var fileContent = reader.ReadToEnd();
var parsedContentDisposition = ContentDispositionHeaderValue.Parse(formData.ContentDisposition);
var fileName = parsedContentDisposition.FileName;
}
return Json(new { result = "Test" });
}

How to send anti forgery token with Ajax file upload?

I'm trying to upload file(s) with an ajax call and validate the anti forgery token. I've had a look around and built a method to validate the anti forgery token on the controller. However whenever I have #Html.AntiForgeryToken on the view, my files do not get populated. Even though it validates the anti forgery token. It doesn't seem to be getting sent with the request but I'm unsure why.
ajaxSendOverride:
$(document).ready(function () {
var securityToken = $('[name=__RequestVerificationToken]').val();
$(document).ajaxSend(function (event, request, opt) {
if (opt.hasContent && securityToken) { // handle all verbs with content
var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
// ensure Content-Type header is present!
if (opt.contentType !== false || typeof event.contentType !== 'undefined') {
request.setRequestHeader("Content-Type", opt.contentType);
}
}
});
});
Ajax:
$(document).on("submit", "[data-upload-contract-form]", function (e) {
e.preventDefault();
var formData = new FormData($('[data-upload-contract-form]')[0]);
if ($('[data-upload-file]').val() != "") {
$.ajax({
url: $(this).attr('action'),
data: formData,
type: 'POST',
processData: false,
contentType: false,
headers: {
'__RequestVerificationToken': $('[name=__RequestVerificationToken]').val()
},
success: function (data) {
if (data.Success === true) {
$('[data-contract-error-message]').text();
ReturnDataTableForUploadFile($('[data-upload-file-supplier-contract-id]').val());
table.ajax.reload();
}
else {
$('[data-contract-error-message]').show();
$('[data-contract-error-message]').text(data.ResponseText);
}
}
})
.fail(function () {
$('[data-contract-error-message]').show();
$('[data-contract-error-message]').text("Something went wrong uploading your file, please try again.");
});
}
else {
$('[data-contract-error-message]').show();
$('[data-contract-error-message]').text("No contract to upload");
}
});
Validation:
public sealed class AuthorizeAntiForgeryToken : System.Web.Mvc.FilterAttribute, System.Web.Mvc.IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
var httpContext = filterContext.HttpContext;
var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
AntiForgery.Validate(cookie != null ? cookie.Value : null,
httpContext.Request.Headers["__RequestVerificationToken"]);
}
}
Controller:
public async Task<JsonResult> UploadContract(UploadContract model)
{
if (ModelState.IsValid)
{
try
{
foreach (var item in model.Contracts)
{
string filePath = WebConfigurationManager.AppSettings["SupplierContractPath"] + GetSelectedClientId() + "\\" + item.FileName;
_supplierFileManager.UploadFile(item, filePath);
await _supplierFileManager.SaveContractToDatabase(model.SupplierContractID, item.FileName);
}
return Json(new { Success = true });
}
catch (Exception e)
{
return Json(new { Success = false, ResponseText = e.Message });
}
}
else
{
string errorMessage = "";
foreach (var item in ModelState.Values.SelectMany(r => r.Errors))
{
errorMessage += "<p>" + item.ErrorMessage + "</p>";
}
return Json(new { Success = false, ResponseText = errorMessage });
}
}
How can I send my files with the anti forgery token?
I ran into this problem myself today and ran into this question without an answer. The links to other answers didn't work, but after a while I found the solution.
The anti-forgery token has to be in a form field, not a header. It also has to be the first field in the form data. So to solve it, do:
$(document).on("submit", "[data-upload-contract-form]", function (e) {
e.preventDefault();
var formData = new FormData();
formData.append('__RequestVerificationToken', $('[name=__RequestVerificationToken]').val());
formData.append('file', $('[data-upload-contract-form]')[0]);
if ($('[data-upload-file]').val() != "") {
$.ajax({
url: $(this).attr('action'),
data: formData,
type: 'POST',
processData: false,
contentType: false,
success: function (data) {
if (data.Success === true) {
$('[data-contract-error-message]').text();
ReturnDataTableForUploadFile($('[data-upload-file-supplier-contract-id]').val());
table.ajax.reload();
}
else {
$('[data-contract-error-message]').show();
$('[data-contract-error-message]').text(data.ResponseText);
}
}
})
.fail(function () {
$('[data-contract-error-message]').show();
$('[data-contract-error-message]').text("Something went wrong uploading your file, please try again.");
});
}
else {
$('[data-contract-error-message]').show();
$('[data-contract-error-message]').text("No contract to upload");
}
});
My own function (using jQuery) which works fine: (it's not complete, but at least it reports back it received the file ;))
<script type="text/javascript">
function uploadFileThroughForm(messageId) {
var form = $('#addAttachmentForm');
if (form.valid()) {
var files = $('#filenameToUpload').prop('files');
if (files.length > 0) {
if (window.FormData !== undefined) {
var formData = new FormData();
formData.append("__RequestVerificationToken", $('#addAttachmentForm input[name=__RequestVerificationToken]').val());
formData.append("file", files[0]);
$.ajax({
type: "POST",
url: '#ApplicationAdapter.GetVirtualRoot()Attachment/Add/' + messageId,
contentType: false,
processData: false,
data: formData,
success: function(result) {
alert(result.responseMessage);
},
error: function(xhr) {
alert(xhr.responseText);
}
});
} else {
alert("This browser doesn't support HTML5 file uploads!");
}
}
}
}
</script>
Hope this helps, even if it's been a while since you asked this question!

How to Call Controller Method in File Upload Using Angularjs Webapi

i am trying to upload multiple file using Angularjs and webapi..
This is my html table:
<body ng-app="fupApp">
<div ng-controller="fupController">
<input type="file" id="file" name="file" multiple
onchange="angular.element(this).scope().getFileDetails(this)" />
<input type="button" ng-click="uploadFiles()" value="Upload" />
<!--ADD A PROGRESS BAR ELEMENT.-->
<p><progress id="pro" value="0"></progress></p>
</div>
</body>
Here is my Angularjs Code for multiple file upload(fileupload.js):
var myApp = angular.module('fupApp', []);
myApp.controller('fupController', function ($scope) {
// GET THE FILE INFORMATION.
$scope.getFileDetails = function (e) {
debugger;
$scope.files = [];
$scope.$apply(function () {
debugger;
// STORE THE FILE OBJECT IN AN ARRAY.
for (var i = 0; i < e.files.length; i++) {
$scope.files.push(e.files[i])
}
});
};
// NOW UPLOAD THE FILES.
$scope.uploadFiles = function () {
debugger;
//FILL FormData WITH FILE DETAILS.
var data = new FormData();
for (var i in $scope.files) {
data.append("uploadedFile", $scope.files[i]);
}
// ADD LISTENERS.
var objXhr = new XMLHttpRequest();
objXhr.addEventListener("progress", updateProgress, false);
objXhr.addEventListener("load", transferComplete, false);
// SEND FILE DETAILS TO THE API.
objXhr.open("POST","MailRoute/getDataForUploadFiles");
objXhr.send(data);
}
// UPDATE PROGRESS BAR.
function updateProgress(e) {
debugger;
if (e.lengthComputable) {
document.getElementById('pro').setAttribute('value', e.loaded);
document.getElementById('pro').setAttribute('max', e.total);
}
}
// CONFIRMATION.
function transferComplete(e) {
debugger;
alert("Files uploaded successfully.");
}
});
here is my function in webapi:
public async Task<HttpResponseMessage> getDataForUploadFiles()
{
}
but how to read the file deatils and access the file details from the controller method(getDataForUploadFiles)
Try this
<div ng-controller="Ctrl">
<input type="file" file-upload multiple/>
<ul>
<li ng-repeat="file in files">{{file.name}}</li>
</ul>
</div>
Controller Code
function Ctrl($scope, $http) {
//a simple model to bind to and send to the server
$scope.model = {
name: "",
comments: ""
};
//an array of files selected
$scope.files = [];
//listen for the file selected event
$scope.$on("fileSelected", function (event, args) {
$scope.$apply(function () {
//add the file object to the scope's files collection
$scope.files.push(args.file);
});
});
//the save method
$scope.save = function() {
$http({
method: 'POST',
url: "/MailRoute/getDataForUploadFiles",
//IMPORTANT!!! You might think this should be set to 'multipart/form-data'
headers: { 'Content-Type': false },
transformRequest: function (data) {
var formData = new FormData();
formData.append("model", angular.toJson(data.model));
//now add all of the assigned files
for (var i = 0; i < data.files; i++) {
//add each file to the form data and iteratively name them
formData.append("file" + i, data.files[i]);
}
return formData;
},
//Create an object that contains the model and files which will be transformed
// in the above transformRequest method
data: { model: $scope.model, files: $scope.files }
}).
success(function (data, status, headers, config) {
alert("success!");
}).
error(function (data, status, headers, config) {
alert("failed!");
});
};
};
Handling the data server-side
public async Task<HttpResponseMessage> getDataForUploadFiles()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var root = HttpContext.Current.Server.MapPath("~/App_Data/Temp/FileUploads");
Directory.CreateDirectory(root);
var provider = new MultipartFormDataStreamProvider(root);
var result = await Request.Content.ReadAsMultipartAsync(provider);
if (result.FormData["model"] == null)
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
var model = result.FormData["model"];
//TODO: Do something with the json model which is currently a string
//get the files
foreach (var file in result.FileData)
{
//TODO: Do something with each uploaded file
}
return Request.CreateResponse(HttpStatusCode.OK, "success!");
}

Sending object to a controller in asp.net mvc using ajax

I have issue with sending object contains array to a controller
this is my js code
var messageId = 0;
function DraftMessage()
{
var to = [];
var i = 0;
$('#to option:selected').each(function (index, element) {
to[i++] = $(element).val();
});
console.log(to);
$.ajax({
type: "POST",
url: "#Url.Action("DraftMessage", "Activities")",
datatype: "json",
traditional: true,
async: false,
data: { "id": messageId, "To": to, "Title": $("#title").val(), "Project": $("#project").val(), "AreaId": $("#areaId").val(), "Body": $("#messageBody").val() },
beforeSend: function () { }
}).done(function (Id) {
console.log(Id);
messageId = Id;
});
}
$("input, select, textarea").change(function () { DraftMessage(); });
var contents = $('.note-editable').html();
$(".compose-message").on("blur", ".note-editable", function () {
if (contents != $(this).html()) {
DraftMessage();
contents = $(this).html();
}
});
and this is my controller side
public int DraftMessage(message draftMessage, HttpPostedFileBase[] files = null)
{
return new MessageActions().DraftMessage(draftMessage);
}
my issue is that the ajax request always send the to array as null, I do not know what is wrong so could anyone help me to resolve this issue.
Can you change your request and use
dataType: "json",
contentType: "application/json;charset=utf-8",
This should work. Please let me know.
Try this. Push your object to array and send it as Json.
array.push({yourobject datas here})
$.ajax({
type: "POST",
url: '/DraftMessage/Activities',
contentType: 'application/json',
data: JSON.stringify(array),
success: function (d) {
..
},
error: function (xhr, textStatus, errorThrown) {
console.log(errorThrown);
}
});
Convert your controller function's return type to JSonResult.
Hope helps.
do you want upload file using ajax ?!!
use the normal usage of form not the Ajax.BeginForm then in form submit event
write your code like this:
$('#Form').submit(function () {
var xhr = new XMLHttpRequest();
var fd = new FormData();
var file = $('#Image').val();
if (file) {
var fname = $('#Image')[0].files[0].name;
if (CheckFile(file)) {
var uploadFile = document.getElementById('Image').files[0];
var myArray = [];
myArray.push(uploadFile);
if (myArray.length > 0) {
for (var i = 0; i < myArray.length; i = i + 1) {
fd.append("File1", myArray[i]);
}
}
}
else {
return false;
}
}
fd.append("ID", messageId);
fd.append("Title", $('#Title').val());
fd.append("Project", $('#Project').val());
fd.append("AreaId", $('#AreaId').val());
fd.append("Body", $('#messageBody').val());
var form = $('#Form');
var token = $('input[name="__RequestVerificationToken"]', form).val();
fd.append("__RequestVerificationToken", token);
xhr.open("POST", "/ControllerName/Action/", true);
xhr.send(fd);
xhr.addEventListener("load", function (event) {
if (event.target.response != "OK") {
OnFail(event.target.response);
}
else {
OnSuccess(event);
}
}, false);
return false;
})
server side in controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult actionName(Model pModel){
HttpPostedFileBase File = Request.Files["File1"];
if (File != null && File.ContentLength != 0){
//do what you want
return Content("OK");
}
else{
Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
return Content("Error Messages", System.Net.Mime.MediaTypeNames.Text.Plain);
}
}
You can try a different approach. You can serialize your entire form by doing something like this:
var formdata = $("#frmEmailInfo").serialize();
and then post it to the Controller:
$.ajax(
{
type: "POST",
data: formdata,
dataType: 'json',...

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