My Html code:
<div class="col-md-6">
<img ngf-src="!picFile.$error && picFile" style="height: 150px; width: 200px;">
<input type="file" ngf-select ng-model="picFile" name="file"
accept="image/*" ngf-max-size="2MB"><b>Picture</b><br />
</div>
<div class="col-md-6">
<img ngf-src="!sigFile.$error && sigFile" style="height: 150px; width: 200px;">
<input type="file" ngf-select ng-model="sigFile" name="file"
accept="image/*" ngf-max-size="2MB"><b>Signature</b><br />
</div>
And My angular code
$scope.SaveNewJoinHolder = function (picFile, sigFile) {
if (investor_validity == 1) {
if ($scope.newJoinHolderForm.$valid) {
if (typeof $scope.newJoinHolder.DOB == undefined) {
$scope.newJoinHolder.DOB = null;
}
else {
var datefilter = $filter('date');
$scope.newJoinHolder.DOB = datefilter($scope.newJoinHolder.DOB, 'dd/MM/yyyy');
$scope.newJoinHolder.birth_date = dateconfigservice.FullDateUKtoDateKey($scope.newJoinHolder.DOB);
}
Upload.upload(
{
url: '/InvestorManagement/JoinHolder/SaveNewJoinHolder',
method: 'POST',
fields: $scope.newJoinHolder,
file: { picFile: picFile, sigFile: sigFile },
async: true
})
.success(function () {
toastr.success('Submitted Successfully');
}).error(function () {
toastr.success('Failed');
});
}
}
};
I debugged the code and I got both of the file while debugging. But it is not calling my C# method
public JsonResult SaveNewJoinHolder(tblJoinHolder joinHolder, HttpPostedFileBase picFile, HttpPostedFileBase sigFile)
{
joinHolderFactory = new JoinHolderFactory();
try
{
joinHolder.membership_id = SessionManger.BrokerOfLoggedInUser(Session).membership_id;
joinHolder.changed_user_id = User.Identity.GetUserId();
joinHolder.changed_date = DateTime.Now;
joinHolder.is_dirty = 1;
byte[] image = new byte[picFile.ContentLength];
picFile.InputStream.Read(image, 0, picFile.ContentLength);
joinHolder.photo = image;
byte[] signature = new byte[sigFile.ContentLength];
sigFile.InputStream.Read(image, 0, sigFile.ContentLength);
joinHolder.signature = signature;
joinHolderFactory.Add(joinHolder);
joinHolderFactory.Save();
return Json(new { data = "Successfully Saved Data", success = true });
}
catch (Exception ex)
{
return Json(new { data = ex.Message, success = false });
}
}
What is the problem here?
If I try to upload single image it is working.
Before version 7.2.0 you couldn't specify a map as file option so you had to do
Upload.upload(
{
url: '/InvestorManagement/JoinHolder/SaveNewJoinHolder',
method: 'POST',
fields: $scope.newJoinHolder,
file: [picFile, sigFile],
fileFormDataName: ['picfile', 'sigFile'],
})
But since version 7.2.0 your original code should work.
You can verify the network tab of your browser to make sure that the file form data is being sent to the server.
Related
I'm using the code from this tutorial to upload rows to a SQL Server table and one of the new requirements it's getting files stored into the server for "Evidence" purposes, so in the form I have the following code:
#using (Html.BeginForm("AnadirLic", "Licencia", FormMethod.Post, new { enctype = "multipart/form-data", onsubmit = "return SubmitForm(this)" }))
{
#Html.HiddenFor(model => model.idLicencia)
<div class="form-group">
<label>Tipo de especialista: </label>
#Html.DropDownList("tipoEspecialista", new List<SelectListItem>{
new SelectListItem{ Value="1", Text = "Medico"},
new SelectListItem{ Value="2", Text = "Dentista"},
new SelectListItem{ Value="3", Text = "Matrona"},})
<small class="form-text text-muted">Ejercicio</small>
</div>
<div class="form-group">
<label>Cargar Evidencia</label>
#*#Html.TextBoxFor(model => model.rutaEvidencia, new { #class = "form-control", #type = "file" })*#
#*#Html.TextBoxFor(model => model.rutaEvidencia, new { #class = "form-control", #type = "file", enctype = "multipart/form-data" })*#
<input type="file" id="FileUpload" />
<small class="form-text text-muted">Máximo 4MB, .pdf, .jpg, .png</small>
</div>
<div class="input-group">
<input type="submit" value="Subir" class="btn btn-primary" style="margin-right:10px"/>
<input type="reset" value="Limpiar campos" class="btn btn-primary" />
</div>
And the AJAX function looks like this:
<script>
function PopupForm(url) {
var formDiv = $('<div/>');
$.get(url)
.done(function (response) {
formDiv.html(response);
Popup = formDiv.dialog({
autoOpen: true,
resizable: true,
title: 'Llenar nuevo reposo',
height: 500,
width: 1300,
close: function () {
Popup.dialog('destroy').remove();
}
})
}
)
}
function SubmitForm(form) {
$.validator.unobtrusive.parse(form);
// FILE VALIDATOR / COUNT
var totalFiles = document.getElementById("FileUpload").files.length;
for (var i = 0; i < totalFiles; i++) {
var archivo = document.getElementById("FileUpload").files[i];
form.append("FileUpload", archivo);
}
//IF VALID UPLOAD TO SQL
if ($(form).valid()) {
$.ajax({
type: "POST",
url: form.action,
data: $(form).serialize(),
success: function (data) {
if (data.success) {
Popup.dialog('close');
$('#tablaLicencia').DataTable().ajax.reload()
$.notify(data.message, {
globalPosition: "top center",
className: "success"
})
}
}
});
}
return false;
}
</script>
Finally the C#:
[HttpPost]
public ActionResult AnadirLic(licenciasUsuario lic)
{
using (TH_mantenedorLicenciasEntities db = new TH_mantenedorLicenciasEntities())
{
var fechaYMD = DateTime.Now.ToString("yyyyMMdd");
var fechaHM = DateTime.Now.ToString("hhmm");
var InputFileName = "";
var ServerSavePath = "";
for (int i = 0; i < Request.Files.Count; i++)
{
var archivo = Request.Files[i];
InputFileName = Path.GetFileName(archivo.FileName);
ServerSavePath = Path.Combine(Server.MapPath("~/evCargadas") + fechaYMD + "_" + fechaHM + "_" + InputFileName);
//Save file to server folder
archivo.SaveAs(ServerSavePath);
}
ViewBag.Message = "Archivo subido correctamente.";
db.licenciasUsuario.Add(lic);
db.SaveChanges();
//UPDATE CON RUTA DE ARCHIVO
lic.rutaEvidencia = ServerSavePath;
db.Entry(lic).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
return Json(new { success = true, message = "Licencia guardada exitosamente." }, JsonRequestBehavior.AllowGet);
}
}
What I've faced is that the FileUpload is always null and using HttpPostFileBase returns the same, therefore the method throws a null exception to the Entity and based on some answers on SO, MVC conflicts with these kind of ajax apps.
System.Data.Entity.Validation.DbEntityValidationException: 'Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.'
Is it possible to emulate a function that allows/force a file upload into a project folder using the same popup thing?
<input type="file" id="FileUpload" /> lets you to select single file. In submit function you are accessing files property which is available only for multiple files selection.
So, either add multiple to your input tag <input type="file" id="FileUpload" multiple />
or modify submit function to use "value" property instead of files property.
function SubmitForm(form) {
$.validator.unobtrusive.parse(form);
// FILE VALIDATOR / COUNT
/*var totalFiles = document.getElementById("FileUpload").files.length;
for (var i = 0; i < totalFiles; i++) {
var archivo = document.getElementById("FileUpload").files[i];
form.append("FileUpload", archivo);
}*/
var archivo = document.getElementById("FileUpload").Value;
form.append("FileUpload", archivo);
//IF VALID UPLOAD TO SQL
if ($(form).valid()) {
$.ajax({
type: "POST",
url: form.action,
data: $(form).serialize(),
success: function (data) {
if (data.success) {
Popup.dialog('close');
$('#tablaLicencia').DataTable().ajax.reload()
$.notify(data.message, {
globalPosition: "top center",
className: "success"
})
}
}
});
}
return false;
}
What can I do to send FormData to my server, my file is always null in server or return Unsupported Media status 415, I try to solve the problem but have no idea now....
<form enctype="multipart/form-data" name="add_data" id="add_data" method="post" onsubmit="return false" >
<input type="file" multiple="multiple" name="files" value="" id="files" />
<br />
<input type="submit" class="btn btn-success" value="Upload">
<br />
</form>
this my html part and then
ajax
$('#add_data').submit(function () {
var totalFiles;
totalFiles = document.getElementById("files").files[0];
var formData = new FormData();
formData.append("files", totalFiles);
$.ajax({
url: "/api/food/addfile",
type: "Post",
data:myData,
contentType: false,
processData: false,
beforeSend: function (request) {
request.setRequestHeader("Authorization", "Bearer " + token);
},
data: totalFiles ,
dataType: 'json',
success: function () {
alert("success")
},
error: function (jqXHR, exception) {
if (jqXHR.status == 401) {
return alert("請先執行前置作業");
}
alert(jqXHR.responseText);
}
});
});
and Controller
[Authorize]
[HttpPost,Route("addfile")]
public IActionResult GetPicture(/*HttpPostedFileBase[] files*/)
{
#region test1
//if (files != null)
//{
// foreach (HttpPostedFileBase file in files)
// {
// file.SaveAs(Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/upload/"), file.FileName));
// }
//}
#endregion
#region test2
var req = System.Web.HttpContext.Current.Request;
if (req.Files.Count > 0)
{
foreach (string fileName in req.Files.Keys)
{
var file = req.Files["files"];
file.SaveAs(Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/upload/"), file.FileName));
}
}
#endregion
return Json(new { Status = 1 > 0 ? "SUCCESS" : "FAILS" });
that all Code , please who can tell me thanks.
I'm trying to achieve to pass a file from the client to my controller in mvc in order to transform the file to a ByteArray, I was thinking that was a simple task but it actually giving me some hard times.. so far I'm able to hit correctly my controller:
HTML
<form method="post" id="myform" enctype="multipart/form-data"
asp-controller="UploadFiles" asp-action="Index">
<div class="form-group">
<div class="col-md-10">
<p>Seleziona un file ORI ed un file MOD.</p>
<label for="fileOri">Seleziona ORI</label>
<input id="fileOri" type="file" name="fileOri" multiple />
<p></p>
<label for="fileMod">Seleziona MOD</label>
<input id="fileMod" type="file" name="fileMod" multiple />
<p></p>
<input id="check" name="checkBoxCorreggi" type="checkbox" />
<label for="check">Correggi Checksum</label>
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<p></p>
<input type="submit" id="VerificaChecksum" value="Verifica Checksum" />
<!--value= "Verifica Checksum-->
<p></p>
</div>
</div>
</form>
JavaScript
$(function () {
$('#VerificaChecksum').click(function () {
var file = document.getElementById('fileOri'),
formData = new FormData();
if (file.files.length > 0) {
for (var i = 0; i < file.files.length; i++) {
formData.append('file' + i, file.files[i]);
}
}
$.ajax({
url: '#Url.Action("UploadFiles", "UploadFiles")',
type: 'POST',
data: formData,
dataType: "json",
cache: false,
contentType: false,
processData: false
});
});
});
MVC CONTROLLER
public class UploadFilesController : Controller
{
int result = 0;
int count = 0;
byte[] fileOri;
byte[] fileMod;
[DllImport(#"c:\Windows\System32\inetsrv\dll194.dll", EntryPoint = "get_cks_XXX")]
public static extern int get_cks_XXX(byte[] pBuf_mod, byte[] pBuf_ori, int len_Buf, bool flag);
private readonly IHostingEnvironment _hostingEnvironment;
public UploadFilesController(IHostingEnvironment hostingEnvironment)
{
this._hostingEnvironment = hostingEnvironment;
}
#region snippet1
[HttpPost("UploadFiles")]
public async Task<IActionResult> Post(IList<IFormFile> files, string[] checkBoxCorreggi)
{
long size = files.Sum(f => f.Length);
// full path to file in temp location
var filePath = Path.GetTempFileName();
foreach (var formFile in files)
{
if (formFile.Length > 0)
{
using (var stream = new MemoryStream())
{
await formFile.CopyToAsync(stream);
if (count == 0)
{
fileOri = stream.ToArray();
}
else
{
fileMod = stream.ToArray();
}
}
}
count++;
}
if (checkBoxCorreggi.Length == 1)
{
result = get_cks_XXX(fileMod, fileOri, fileOri.Length, true);
return File(fileMod, "application/force-download", "modCorretto.mod");
}
else
{
result = get_cks_XXX(fileMod, fileOri, fileOri.Length, false);
return Ok(new { count = files.Count, size, filePath });
}
}
#endregion
}
As I said before I'm currently able to hit my controller, but the problem is that the IList<IFormFile> files is actually null, where I'm getting wrong?
I hope this will work.
I have just only one file to send so i am doing this is Asp.Net Core
You can add your conditions as well like Files.Count or something you want.
Here is my code to save file
[HttpPost]
public async Task<JsonResult> SaveRegistration(string registration)
{
var message = "";
var status = "";
try
{
var path = Path.Combine(_hostingEnvironment.WebRootPath, "Files\\Images");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
path += "\\";
if (!string.IsNullOrEmpty(registration))
{
var reg = new Registration();
reg.Name = registration;
var file = Request.Form.Files[0];
if (file != null)
{
var fileName = file.FileName;
if (System.IO.File.Exists(path + fileName))
{
fileName = $"{DateTime.Now.ToString("ddMMyyyyHHmmssfff")}-{fileName}";
}
using (var fileStream = new FileStream(path + fileName, FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
reg.Picture = fileName;
}
_context.Registration.Add(reg);
await _context.SaveChangesAsync();
message = "Data is not saved";
status = "200";
}
}
catch (Exception ex)
{
message = ex.Message;
status = "500";
}
return Json(new
{
Message = message,
Status = status
});
}
I'm currently working on a project where the previous contractor had an attachments area within our site. The piece works for the most part but has issues when redirecting back after uploading the file, plus I don't like the fact the page does a full page reload just to update a grid to show the uploaded file.
My goal is to instead do an Ajax call for the upload versus form submit. I have added this in, however, the return forces a download of the Json object (using IE 11). I have researched how to get around this and have yet to find any substantial ways around it.
Is it possible to upload a file using Ajax and not send back a download of the Json object?
Below is my code.
View (Upload.cshtml)
#using (Html.BeginForm("Upload", "PM", FormMethod.Post, new { enctype = "multipart/form-data", id = "frmUpload" }))
{
#Html.ValidationSummary(true)
<table>
...
<tr>
<td>#Html.Label("File: ")</td>
<td>
<input type="file" name="file" id="file"/>
#Html.ValidationMessage("file","File is required")
</td>
</tr>
...
<tr>
<td colspan="2">
<p>
<button type="submit" class="t-button" id="btnSubmit">
Attach</button>
<button type="button" class="t-button" onclick="CloseAttachmentWindow()">
Cancel</button>
</p>
</td>
</tr>
</table>
}
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function (e) {
e.preventDefault();
if (!$('form').valid())
return false;
//Upload document
$.ajax({
type: "POST",
cache: false,
url: "/PM/Upload",
dataType: "json",
contentType: false,
processData: false,
data: $('form').serialize(),
success: function (result) {
if (result.success) {
var window = $("#error").data("tWindow");
window.content("<b>Attachment successfully added</b>").title("Success!");
window.center().open();
CloseAttachmentWindow();
}
else {
var window = $("#error").data("tWindow");
window.content("<b>Error: Unable to Upload Document. Please try again. "
+ "If this fails, contact the administrators with the below details.</b>"
+ '\n' + '\n' + result.Error).title("Error");
window.center().open();
}
},
error: function (xhtr, e, e2) {
var window = $("#error").data("tWindow");
window.content(e + '\n' + xhtr.responseText, 'error', '');
window.center().open();
}
});
});
});
</script>
PMController.cs
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file, FormCollection formcollection)
{
if (file != null)
{
var cntPOC = int.Parse(Session["cntPOC"].ToString());
try
{
var cntFileType = _fileTypeRepo.GetCntFileTypeByMimeType(file.ContentType);
if (cntFileType == 0)
throw new Exception("This file type is not supported");
var strAttachmentName = formcollection["AttachmentName"];
var strAttachmentType = formcollection["AttachmentType"];
var length = file.ContentLength;
var tmpFile = new byte[length];
if (tmpFile.Count() > 0)
{
file.InputStream.Read(tmpFile, 0, length);
var intAttchmentId = _AttachRepo.GetNextAttachmentId() + 1;
var objAttachment = new TBLATTACHMENT
{
CNTATTACHMENT = intAttchmentId,
CNTPOC = cntPOC,
CNTFILETYPE = cntFileType,
CNTATTACHMENTTYPE = Convert.ToDecimal(strAttachmentType),
DTMCREATED = DateTime.Now,
STRATTACHMENTTITLE = strAttachmentName,
BLBATTACHMENT = tmpFile,
STRORIGINALFILENAME = file.FileName,
YSNDELETED = 0
};
_AttachRepo.Add(objAttachment);
_AttachRepo.Save();
return Json(new { success = true, Error = "" });
}
//File not real
else
return Json(new { success = false, Error = "Please select appropriate file" });
}
catch (Exception ex)
{
logger.LogError("File Upload", ex);
if (ex.InnerException != null)
ModelState.AddModelError("Error", ex.InnerException.ToString());
else
ModelState.AddModelError("Error", ex.Message.ToString());
TempData["ModelState"] = ModelState;
return Json(new { success = false, Error = ex.Message });
}
}
else
{
logger.LogError("File Upload Error. File was not selected");
ModelState.AddModelError("Error", "Please select file");
TempData["ModelState"] = ModelState;
return Json(new { success = false, Error = "File was not selected" });
}
}
As is, using this code, I can upload documents, however, I get the prompt to download the Json object upon return.
NOTE Long story short, you cannot do this. I had to learn the hard way and never did find a solution. I did find a way to do it for downloads, but not uploads.
Options:
Remove change the button type submit to button <input type="button"/>
<input type="submit" onclick="return false">
return false; or add event handlers
$("input[type='submit']").click(function() { return false; });
or
$("form").submit(function() { return false; });
<form onsubmit="return false"> ...</form>
in order to avoid refresh at all "buttons", even with onclick assigned.
changing the submit type to button is the optimal one.
I am having problem with getting the progress bar working properly I have setup for when a file is uploaded. The progress bar works fine but however the bar doesn't work in sync with the size of the file. So if the file is 80 MB and if the file is still being processed in the back end the progress bar will always says upload 100%.
I am not sure where am going wrong in the code? Basically want the progress bar to be in sync with code being processed in the back end.
Here is progress so far
Controller:
//
// POST
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UploadMultipleFiles(IEnumerable<HttpPostedFileBase> files)
{
int count = 0;
if (files != null)
{
foreach (var file in files)
{
if (file != null && file.ContentLength > 0)
{
FileUploadService service = new FileUploadService();
var postedFile = Request.Files[0];
StreamReader sr = new StreamReader(postedFile.InputStream);
StringBuilder sb = new StringBuilder();
DataTable dt = CreateTable();
DataRow dr;
string s;
int j = 0;
while (!sr.EndOfStream)
{
while ((s = sr.ReadLine()) != null)
{
//Ignore first row as it consists of headers
if (j > 0)
{
string[] str = s.Split(',');
dr = dt.NewRow();
dr["Postcode"] = str[0].ToString();
dr["Latitude"] = str[2].ToString();
dr["Longitude"] = str[3].ToString();
dr["County"] = str[7].ToString();
dr["District"] = str[8].ToString();
dr["Ward"] = str[9].ToString();
dr["CountryRegion"] = str[12].ToString();
dt.Rows.Add(dr);
}
j++;
}
}
// Save to database
service.SaveFilesDetails(dt);
sr.Close();
count++;
}
}
}
return new JsonResult { Data = "Successfully " + count + " file(s) uploaded" };
}
View:
#{
ViewBag.Title = "File Upload";
Layout = "~/Views/Shared/_LayoutPage.cshtml";
}
<h2>Upload a CSV File</h2>
#using (Ajax.BeginForm("UploadMultipleFiles", "File", new AjaxOptions() { HttpMethod = "POST" }, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="row">
<div class="col-md-5">
<input type="file" name="files" id="fu1" />
</div>
<div class="col-md-2">
<input type="submit" class="btn btn-default" value="Upload File" />
</div>
</div>
}
<div class="progress">
<div class="progress-bar">0%</div>
</div>
<div id="status"></div>
<div id="loading" class="loader">Loading...</div>
<style>
.progress {
position: relative;
width: 400px;
border: 1px solid #ddd;
padding: 1px;
}
.progress-bar {
width: 0px;
height: 20px;
background-color: #57be65;
}
</style>
#section scripts{
<script src="http://malsup.github.com/jquery.form.js"></script>
<script>
$(document).ready(function () {
(function () {
var bar = $('.progress-bar');
var percent = $('.progress-bar');
var status = $('#status');
$('#loading').hide();
$('form').ajaxForm({
beforeSend: function () {
status.empty();
var percentValue = '0%';
bar.width(percentValue);
percent.html(percentValue);
},
uploadProgress: function (event, position, total, percentComplete) {
var percentValue = percentComplete + '%';
bar.width(percentValue);
percent.html(percentValue);
$('#loading').show();
},
success: function (d) {
var percentValue = '100%';
bar.width(percentValue);
percent.html(percentValue);
$('#fu1').val('');
$('#loading').hide();
//alert(d);
},
complete: function (xhr) {
status.html(xhr.responseText);
}
});
})();
});
</script>
}
Your code is working fine. You have upload progress, so you only get percent of data passed to server. After that your client have no idea how long server processes your data and how much of it has been processed.
In fact the only long time running operation you have after file is uploaded is saving it to the database. As I know there is no way you can know how much time the query left to complete, so you can't get progress. So the only thing I can suggest here is to switch to some inifinite loading icon with "processing" label after file upload is 100% complete.
In case you had more than one long time running operations you could pass progress after each operation via SignalR for example. But you won't be able to get progress of each operation (of course depends on operation) only percent of operations completed.