I have a client built in Angular. I am trying to upload files that are to be processed by the asp.net server side code. Although I have managed to get files in the file control but I don't know how I can pass the binary data to server side. My client side code looks as follows
HTML Code
<div>
<form name="form1" method="POST" enctype="multipart/form-data">
<div>
{{repopulatecftcModel.title}}
</div>
<div style="padding-top:15px;padding-bottom:15px;"><b>Toolkit - Repopulate Cftc Data</b></div>
<div>
<input type="file" id="updCftcFileUploader" name="files[]" multiple />
</div>
<div>
<input type="button" value="Upload Files" title="Upload Files" ng-click="UploadCFTCFiles()" />
</div>
<div>
<label ng-model="repopulatecftc.validationtext"></label>
</div>
<div>
{{repopulatecftcModel.validationtext}}
</div>
</form>
Controller Code in Angular
function controller($scope, $http, AppModel, WebFunctionService) {
$scope.UploadFiles = function (evt) {
var files = document.getElementById('updFileUploader').files;
for(var i = 0; i < files.length; i++) {
var file = files[i];
if (file) {
// getAsText(file);
alert("Name: " + file.name + "\n" + "Last Modified Date :" + file.lastModifiedDate);
}
}
var parameters = { directory: $scope.defaultsSaveDirectory, filename: "" };
WebFunctionService.promiseWebMethod('UploadFiles', angular.fromJson(parameters), true)
.success(function () {
$scope.userMessage = "File(s) successfully uploaded";
console.log($scope.userMessage);
})
.error(function (error) {
$scope.userMessage = "ERROR uploading files" + error;
console.log($scope.userMessage);
});
};
};
Server side code where I want to access the uploaded files from
[Route("UploadFiles")]
[HttpPost]
public void UploadFiles()
{
}
When I run the code I do get alerts for each of the file being uploaded. Then the code get into the server side as shown in the image below
Its here that I want to access the files from. I have seen in the web where they show Request.Files shows the collection of files being uploaded but when I try to do that the compiler starts complaining.
Anyone have any clues as to how I should be able to pass binary data being uploaded from client side in this case and access it from the server side
In angular when you call the server side you can use $upload to upload a file here is an example:
var uploadFile = function (file, args) {
var deferred = $q.defer();
$upload.upload({
url: "<your url goes here>",
method: "POST",
file: file,
data: args
}).progress(function (evt) {
// get upload percentage
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function (data, status, headers, config) {
// file is uploaded successfully
deferred.resolve(data);
}).error(function (data, status, headers, config) {
// file failed to upload
deferred.reject();
});
return deferred.promise;
}
The above function will pass the file along with extra args if you need it.
Server side
[HttpPost]
public async Task<HttpResponseMessage> AddFile()
{
if (!Request.Content.IsMimeMultipartContent())
{
this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/temp/uploads");
var provider = new MultipartFormDataStreamProvider(root);
var result = await Request.Content.ReadAsMultipartAsync(provider);
// On upload, files are given a generic name like "BodyPart_26d6abe1-3ae1-416a-9429-b35f15e6e5d5"
// so this is how you can get the original file name
var originalFileName = GetDeserializedFileName(result.FileData.First());
var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);
string path = result.FileData.First().LocalFileName;
//Do whatever you want to do with your file here
return this.Request.CreateResponse(HttpStatusCode.OK, originalFileName );
}
private string GetDeserializedFileName(MultipartFileData fileData)
{
var fileName = GetFileName(fileData);
return JsonConvert.DeserializeObject(fileName).ToString();
}
public string GetFileName(MultipartFileData fileData)
{
return fileData.Headers.ContentDisposition.FileName;
}
Related
I'm building a file upload web application using ASP.NET Core 6 and I would like the user to be able to confirm whether or not to overwrite an existing file. The application allows for multiple file uploads
Questions:
where to check if the file exists? (i.e. client-side or on the server)
if on the client-side how to check if file exists on the server?
how to handle the POST request so that it can "wait" for user confirmation?
is this kind of "communication" with the user even possible in ASP.NET Core 6? or should I be using Blazor or Signal R (I'm really new to .NET)
This is my form:
<form method="POST" enctype="multipart/form-data">
<input type="file" multiple name="files">
<button type="submit" class="btn custom-button">Upload Files</button>
</form>
This is the controller action:
[HttpPost]
public async Task<IActionResult> UploadFiles(IEnumerable<IFormFile> files, string folders)
{
foreach (var file in files)
{
string trimmedFileName = String.Concat(file.FileName.Where(c =>!Char.IsWhiteSpace(c)));
var filePath = Path.Combine(folders, trimmedFileName);
if (System.IO.File.Exists(filePath))
{
ViewBag.Error = $"File {trimmedFileName} already exists on the server";
this.Redirect("UploadFiles");
}
using var filestream = System.IO.File.Create(filePath);
await file.CopyToAsync(filestream);
}
}
I have simplified the above code so as not too add too much detail
Attempts
I have tried AJAX calls to stop the POST request and add some logic but I don't seem to be able to access the folder on the server to even check if the file already exists
$("#uploadForm").submit(function(e){
e.preventDefault();
let files = $(".form-control-file")[0].files;
for (let i = 0; i < files.length; i++){
let url = $("#filePathUrl").val() + "/" + files[i].name;
if(url){
$.ajax({
url: url,
type: 'HEAD',
error: function(){
alert(files[i].name + " exists!");
},
success: function(){
alert(files[i].name + " does not exist on server");
I have simplified and removed closing braces from the above code to keep things simple
Here's what you can do,
Use AjaxRequest to submit the form (by preventing default)
In Controller Action save files if all the files are new
Dont save files if there is any duplicate. Send a message to the client stating that these files are duplicate, Do you want to overwrite these files?
if user says "Yes", send the same AjaxRequest again with an additional parameter and Save all the files (with overwriting duplicate files)
If user says "No", then nothing needs to be done
Lets move to code
JS
function processFiles(confirmOverwrite = false){
const files = $(".form-control-file")[0].files;
const formData = new FormData();
files.forEach(file => formData,append('files[]', file));
const folderName = 'Uploads';
const url = $("#filePathUrl").val();
$.ajax({
url: url+'?folders='+folderName+'&confirmOverwrite='+confirmOverwrite,
type: 'POST',
data: formData,
processData: false,
success: (response) =>{
if(response.Status){
alert('Files uploadedn successfully');
}
else{
if(response.Message){
if(confirm(response.Message + ' files already exist. Do you want to overwrite these?')){
processFiles(true);
}
else{
alert('Files not uploaded');
}
}
}
},
error: (a,b,c) => {
console.error({a,b,c});
}
});
}
$("#uploadForm").submit(function(e){
e.preventDefault();
processFiles(false);
});
Controller
[HttpPost]
public async Task<IActionResult> UploadFiles(IEnumerable<IFormFile> files, string folders, bool confirmOverwrite = false)
{
var existingFiles = new List<string>();
var filesToBeSaved = new List<(IFormFile file, string filePath)>();
foreach (var file in files)
{
string trimmedFileName = file.FileName.Replace(" ", "");
var filePath = Path.Combine(folders, trimmedFileName);
if (System.IO.File.Exists(filePath) && !confirmOverwrite)
{
existingFiles.Add(file.FileName + "("+ trimmedFileName + ")");
}
else
{
filesToBeSaved.Add((file, filePath));
}
}
if (existingFiles.Any())
{
return Json(new { Status = false, Message = string.Join(", ", existingFiles) });
}
else
{
foreach (var (file, filePath) in filesToBeSaved)
{
using var filestream = System.IO.File.Create(filePath);
await file.CopyToAsync(filestream);
}
return Json(new { Status = true, Message = "Success" });
}
}
Your POST to upload the file could return a 409 Conflict status if a file already exists. The UI would then detect this on first posting, and show a popup. If the user selects 'continue', then the POST could include a query parameter to say the user has confirmed the OK is allowed. Something like this:
[HttpPost]
public async Task<IActionResult> UploadFiles(bool? allowOverwrite, IEnumerable<IFormFile> files, string folders)
{
foreach (var file in files)
{
string trimmedFileName = String.Concat(file.FileName.Where(c => !Char.IsWhiteSpace(c)));
var filePath = Path.Combine(folders, trimmedFileName);
if (!allowOverwrite.GetDefaultValue() && System.IO.File.Exists(filePath)) < ---
{
ViewBag.Error = $"File {trimmedFileName} already exists on the server";
return Conflict(); < ---
}
using var filestream = System.IO.File.Create(filePath);
await file.CopyToAsync(filestream);
}
}
I'm a little lost on what should I do. I'm trying to upload a file along with its form data in one click, but I can't get the file. I tried to check the file in client and it's okay, but when receiving the file in the Controller, it's empty.
Problem
How do I upload the file along its formData using jQuery?
View
Assuming the other fields
<form id="_RegisterProduct" enctype="multipart/form-data">
<div>
<label>Product Description</label>
<textarea id="product_description" name="_product_description"></textarea>
<input type="file"
id="product_file"
name="product_file"
class="dropify" />
</div>
<button type="submit" id="snippet_new_save">Register Product</button>
</form>
<script>
$(function() {
rules: {
text: { required: true, minlength: 5 },
number: { required: true, minlength: 1 }
},
submitHandler: function (form) {
var fileUpload = $("#product_file").val();
var formData = $("#_RegisterForm").serialize();
var url = "#Url.Action("RegisterProduct", "Product")";
$.get(url, { fileUpload: fileUpload, formData }, function (e) {
if (e >= 1) {
console.log("success");
} else {
console.log("error");
}
});
}
})
</script>
Controller
public string RegisterProduct(HttpPostedFileBase fileUpload, AB_ProductModel formData)
{
var data = "";
using (var con = new SqlConnection(Conn.MyConn()))
{
var path = Server.MapPath("~/Content/uploads/products");
var Extension = "";
var fileName = "";
try
{
if(fileUpload.ContentLength > 0)
{
Extension = Path.GetExtension(fileUpload.FileName);
fileName = Path.GetFileName(fileUpload.FileName);
var com = new SqlCommand("dbo.sp_some_stored_procedure_for_saving_data",
con);
con.Open
data = Convert.ToString(com.ExecuteScalar());
var file_path = Path.Combine(path, data + Extension);
fileUpload.SaveAs(file_path);
}
}
catch (Exception ex)
{
data = ex.Message;
}
// data returns id if success or error message
}
return data;
}
Why serialize the form? This method creates a string that can be sent over to the server, but that is not what you want to do... In case of a file upload; see .serialize() function description here.
FormData type automatically manages the enctype for your forms (see here on MDN), so you can omit that—although you should consider using it, because it helps other members on the team understand the intent. If you want to use plain jQuery, you can simply attach the formData variable to the data field of the $.ajax call. See like here,
/*
* i know id-based selection should only have 1 element,
* otherwise HTML is invalid for containing multiple elements
* with the same id, but this is the exact code i used back then, so using it again.
**/
var formData = new FormData($('#form')[0]);
$.ajax({
type: 'POST',
processData: false,
contentType: false,
data: formData,
success: function (data) {
// The file was uploaded successfully...
$('.result').text('File was uploaded.');
},
error: function (data) {
// there was an error.
$('.result').text('Whoops! There was an error in the request.');
}
});
This of course requires that your HTML DOM contains these elements—I used the code I wrote for my article quite a few years back. Secondly, for my other part of the feature, I used Request.Files to capture the files that might have been uploaded with the request.
files = Request.Files.Count;
if(files > 0) {
// Files are sent!
for (int i = 0; i < files; i++) {
var file = Request.Files[i];
// Got the image...
string fileName = Path.GetFileName(file.FileName);
// Save the file...
file.SaveAs(Server.MapPath("~/" + fileName));
}
}
This way, I uploaded the files using jQuery and FormData.
You can check out the complete article I posted here, Uploading the files — HTML5 and jQuery Way!
Oh, and do not forget the suggestion made in the comment,
using (var com = new SqlCommand("dbo.sp_some_stored_procedure_for_saving_data", con))
{
con.Open(); // missed call?
data = Convert.ToString(com.ExecuteScalar());
// although, using should close here!
var file_path = Path.Combine(path, data + Extension);
fileUpload.SaveAs(file_path);
}
So, this was pretty much how you can do this.
I am using a custom section within umbraco for displaying messages sent by users. I want the admins to be able to answer these messages by uploading a file to the message itself. This way I will know which file belongs to which message. I have followed some guides and recommendations most notably this one
file-upload-in-backoffice-custom-section on how to upload files from umbraco backoffice.
Problem with my code however is that it does not seem to send the whole file with the post request just the path of the file which becomes something similar to: C:\fakepath\file.pdf
My question would be how do I send the whole file in the post request and how can i catch/convert the file into an HttpPostedFileBase inside of the API function. If I can get the file as HttpPostedFileBase I will know how to upload it to the media section of umbraco.
Code below:
edit.html:
<umb-control-group label="File" description="File to upload">
<input type="file" class="umb-editor umb-textstring" ng-model="files" ng-change="fileSelected(files)" ng-multiple="false" />
</umb-control-group>
</div>
</div>
</div>
</umb-editor-container>
<umb-editor-footer>
<umb-editor-footer-content-right>
<div class="umb-button ng-scope">
<button ng-click="OnSave()" class="btn umb-button__button btn-success umb-button--">
<span class="umb-button__content">
Save
</span>
</button>
</div>
</umb-editor-footer-content-right>
</umb-editor-footer>
edit.controller.js:
$scope.fileSelected = function (files) {
$scope.file = files;
};
$scope.OnSave = function () {
var request = {
file: $scope.file
};
return $http({
method: 'POST',
url: "backoffice/Messages/MessagesApi/PostSaveFile",
headers: { 'Content-Type': undefined },
transformRequest: function (data) {
var formData = new FormData();
formData.append("file", data.file);
return formData;
},
data: request
}).then(function (response) {
if (response) {
var fileName = response.data;
return fileName;
} else {
return false;
}
});
};
MessagesApiController.cs:
public HttpResponseMessage PostSaveFile(HttpPostedFileBase file)
{
var files = HttpContext.Current.Request;
if (files != null && files.ContentLength > 0)
{
StreamReader reader = new StreamReader(files.InputStream);
string responseFromServer = reader.ReadToEnd();
}
return Request.CreateResponse(HttpStatusCode.OK);
}
If anyone is stumbling accross this issue this is how I managed to solve it:
edit.html:
<umb-control-group label="Response File" description="File to upload">
<input type="file" id="myFile" ng-multiple="false" />
</umb-control-group>
edit.controller.js:
if ($element.find('#myFile')[0].files[0] !== undefined) {
var fd = new FormData();
fd.append('file', $element.find('#myFile')[0].files[0]);
$http.post("backoffice/Messages/MessagesApi/PostSaveFile", fd, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).success(function (response) {
console.log(response);
});
}
MessagesApiController.cs:
public string PostSaveFile()
{
var file = HttpContext.Current.Request.Files["file"];
return file.FileName;
}
Variable file is now an HttpPostedFile and you can use it for whatever you want like saving it into the media section.
For those of you who are struggling with file uploads in custom sections in Umbraco 8 here's my solution:
View:
<input type="file" class="umb-textstring" ngf-select="" ng-model="files" ng-multiple="false" ngf-change="fileSelected(files)" required />
<umb-button action="vm.clickUploadButton()"
type="button"
button-style="info"
label="Upload">
</umb-button>
Controller:
function Controller($scope, Upload) {
var vm = this;
vm.clickUploadButton = clickUploadButton;
$scope.fileSelected = function (files) {
$scope.file = files;
};
function clickUploadButton() {
if (!$scope.file)
return false;
Upload.upload({
url: "backoffice/api/Upload/UploadFile",
fields: {
"field1": "value1",
"field2": "value2"
},
file: $scope.file
}).success(function (data, status, headers, config) {
console.log(status);
console.log(data);
}).error(function (evt, status, headers, config) {
console.log(evt.Message);
});
}
}
API controller:
public class UploadController : UmbracoAuthorizedApiController
{
[HttpPost]
public HttpResponseMessage UploadFile()
{
var files = HttpContext.Current.Request.Files;
var field1 = HttpContext.Current.Request.Form["field1"];
var field2 = HttpContext.Current.Request.Form["field2"];
return Request.CreateResponse(HttpStatusCode.OK, new { fileCount = files.Count, field1, field2 }) ;
}
}
I am building a CMS as MVC 4 project and one of the features is to upload your photo. The user chooses a photo from his hard drive, which triggers an ajax request to the UploadFile method on the controller. This should copy the photo to a virtual folder on the server. The problem is I don't really understand where the browser stores the file and sends it to the server, and what I am supposed to do on the controller.
This is my code so far -
The view:
<input id="cng_pic_btn" type="file" name="file" accept="image/*" /></td>
JavaScript making the call to the server:
$('#cng_pic_btn').live('change', function () {
custom_url = "/SideBar/UploadFile";
return_msg = "file uploaded";
var file_path = $('#cng_pic_btn').attr("value");
alert(file_path);
sendInfo = {
upload_from: file_path
}
CreataAjaxRequest(custom_url, sendInfo, return_msg);
})
The conroller method:
[HttpPost]
public void UploadFile(string upload_from)
{
string path = #"D:\Temp\";
HttpPostedFileBase photo = Request.Files[upload_from];
photo.SaveAs(path + photo.FileName);
}
send ajax request:
function CreataAjaxRequest(custom_url, sendInfo, return_msg) {
$.ajax({ type: "POST", url: custom_url, data: sendInfo })
.success(function (html) {
$(".query-result").replaceWith(html);
})
}
You haven't shown your CreataAjaxRequest method but if you want to upload files using AJAX there are a couple of options:
your client browser supports the HTML 5 File API in which case you could use the XmlHttpRequest2 object
your client browser doesn't support the File API (Such as Internet Explorer) in which case you could use a file upload plugin such as Uploadify or Fine Uploader which use techniques like hidden iframes or Flash movies for those kind of legacy browsers.
Here's an example of how you could upload a file using the HTML 5 File API:
function CreataAjaxRequest(custom_url, sendInfo, return_msg) {
var xhr = new XMLHttpRequest();
var fd = new FormData();
xhr.open('POST', custom_url, true);
var file = document.getElementById('cng_pic_btn').files[0];;
fd.append('myFile', file);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
$('.query-result').replaceWith(xhr.responseText);
}
};
xhr.send(fd);
}
and then on your server:
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase myFile)
{
var path = string path = #"D:\Temp\";
myFile.SaveAs(Path.Combine(path, myFile.FileName));
return PartialView();
}
Also notice that your controller action needs to return a PartialView if you want to use the $('.query-result').replaceWith(xhr.responseText); method in your AJAX callback, otherwise what are you replacing with?
I am working on an ASP.NET MVC 4 Application that imports and processes a CSV file. I am using a standard form and controller for the upload. Here is an overview of what I am doing currently:
Controller Logic
public ActionResult ImportRecords(HttpPostedFileBase importFile){
var fp = Path.Combine(HttpContext.Server.MapPath("~/ImportUploads"), Path.GetFileName(uploadFile.FileName));
uploadFile.SaveAs(fp);
var fileIn = new FileInfo(fp);
var reader = fileIn.OpenText();
var tfp = new TextFieldParser(reader) {TextFieldType = FieldType.Delimited, Delimiters = new[] {","}};
while(!tfp.EndOfData){
//Parse records into domain object and save to database
}
...
}
HTML
#using (Html.BeginForm("ImportRecords", "Import", FormMethod.Post, new { #id = "upldFrm", #enctype = "multipart/form-data" }))
{
<input id="uploadFile" name="uploadFile" type="file" />
<input id="subButton" type="submit" value="UploadFile" title="Upload File" />
}
The import file can contain a large number of records (average 40K+) and can take quite some time to complete. I'd rather not have a user sitting at the import screen for 5+ minutes for each file processed. I have considered adding a console application to watch the uploads folder for new files, and process when something new is added, but would like to see what input I receive from the community before starting my journey down this path.
Is there a more efficient way to handle this operation?
Is there a way to perform this action, allowing the user to continue about his/her merry way, and then notify the user when processing is done?
The solution to the issue I was having is a bit complex, but works similar to the IFrame fix. The result is a pop-up window that handles the processing, allowing the user to continue navigation throughout the site.
The file is submitted to the server (UploadCSV controller), a Success page is returned with a bit of JavaScript to handle the initial kick-off of the processing. When the user clicks "Begin Processing", a new window is opened (ImportProcessing/Index) that loads the initial status (kicking off an interval loop that retrieves status updates) and then makes a call to the "StartProcessing" action, kicking off the processing process.
The "FileProcessor" class that I am using is housed in a static dictionairy variable within the ImportProcessing controller; allowing for status results based on the key. The FileProcessor is promptly removed after the operation is complete or an error is encountered.
Upload Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UploadCSV(HttpPostedFileBase uploadFile)
{
var filePath = string.Empty;
if (uploadFile.ContentLength <= 0)
{
return View();
}
filePath = Path.Combine(Server.MapPath(this.UploadPath), "DeptartmentName",Path.GetFileName(uploadFile.FileName));
if (new FileInfo(filePath).Exists)
{
ViewBag.ErrorMessage =
"The file currently exists on the server. Please rename the file you are trying to upload, delete the file from the server," +
"or contact IT if you are unsure of what to do.";
return View();
}
else
{
uploadFile.SaveAs(filePath);
return RedirectToAction("UploadSuccess", new {fileName = uploadFile.FileName, processType = "sonar"});
}
}
[HttpGet]
public ActionResult UploadSuccess(string fileName, string processType)
{
ViewBag.FileName = fileName;
ViewBag.PType = processType;
return View();
}
Upload Success HTML:
#{
ViewBag.Title = "UploadSuccess";
}
<h2>File was uploaded successfully</h2>
<p>Your file was uploaded to the server and is now ready to be processed. To begin processing this file, click the "Process File" button below.
</p>
<button id="beginProcess" >Process File</button>
<script type="text/javascript">
$(function () {
$("#beginProcess").click(BeginProcess);
function BeginProcess() {
window.open("/SomeController/ImportProcessing/Index?fileName=#ViewBag.FileName&type=#ViewBag.PType", "ProcessStatusWin", "width=400, height=250, status=0, toolbar=0, scrollbars=0, resizable=0");
window.location = "/Department/Import/Index";
}
});
</script>
Once this new window is opened up, the file processing begins. Updates are retrieved from a custom FileProcessing class.
ImportProcessing Controller:
public ActionResult Index(string fileName, string type)
{
ViewBag.File = fileName;
ViewBag.PType = type;
switch (type)
{
case "somematch":
if (!_fileProcessors.ContainsKey(fileName)) _fileProcessors.Add(fileName, new SonarCsvProcessor(Path.Combine(Server.MapPath(this.UploadPath), "DepartmentName", fileName), true));
break;
default:
break;
}
return PartialView();
}
ImportProcessing Index:
#{
ViewBag.Title = "File Processing Status";
}
#Scripts.Render("~/Scripts/jquery-1.8.2.js")
<div id="StatusWrapper">
<div id="statusWrap"></div>
</div>
<script type="text/javascript">
$(function () {
$.ajax({
url: "GetStatusPage",
data: { fileName: "#ViewBag.File" },
type: "GET",
success: StartStatusProcess,
error: function () {
$("#statusWrap").html("<h3>Unable to load status checker</h3>");
}
});
function StartStatusProcess(result) {
$("#statusWrap").html(result);
$.ajax({
url: "StartProcessing",
data: { fileName: "#ViewBag.File" },
type: "GET",
success: function (data) {
var messag = 'Processing complete!\n Added ' + data.CurrentRecord + ' of ' + data.TotalRecords + " records in " + data.ElapsedTime + " seconds";
$("#statusWrap #message").html(messag);
$("#statusWrap #progressBar").attr({ value: 100, max: 100 });
setTimeout(function () {
window.close();
}, 5000);
},
error: function (xhr, status) {
alert("Error processing file");
}
});
}
});
</script>
Finally the Status Checker html:
#{
ViewBag.Title = "GetStatusPage";
}
<h2>Current Processing Status</h2>
<h5>Processing: #ViewBag.File</h5>
<h5>Updated: <span id="processUpdated"></span></h5>
<span id="message"></span>
<br />
<progress id="progressBar"></progress>
<script type="text/javascript">
$(function () {
var checker = undefined;
GetStatus();
function GetStatus() {
if (checker == undefined) {
checker = setInterval(GetStatus, 3000);
}
$.ajax({
url: "GetStatus?fileName=#ViewBag.File",
type: "GET",
success: function (result) {
result = result || {
Available: false,
Status: {
TotalRecords: -1,
CurrentRecord: -1,
ElapsedTime: -1,
Message: "No status data returned"
}
};
if (result.Available == true) {
$("#progressBar").attr({ max: result.Status.TotalRecords, value: result.Status.CurrentRecord });
$("#processUpdated").text(result.Status.Updated);
$("#message").text(result.Status.Message);
} else {
clearInterval(checker);
}
},
error: function () {
$("#statusWrap").html("<h3>Unable to load status checker</h3>");
clearInterval(checker);
}
});
}
});
</script>
Just a thought but you could thread the processing of your CSV files and on completion of that task call another method that basically provides a modal dialog or some kind of javascript alert on the client side letting the user know that the processing has completed.
Task.Factory.StartNew(() => ProcessCsvFile(fp)).ContinueWith((x) => NotifyUser());
or something along those lines. I think that ultimately you are gonna wanna look at some kind of threading because it certainly does not make sense for a user to be stuck looking at a screen while some kind of server side processing takes place.