I am attempting to upload a file. The code below works on my local machine or running on a remote server running the dll from a command line, but when I try and publish to my test environment and run under iis it fails.
<form method="post" asp-action="Upload" asp-controller="Prebook" enctype="multipart/form-data">
<div class="form-inline">
<div class="col-md-2">
<div class="form-group">
<input type="file" name="files" data-input= "false" multiple class="filestyle" data-buttonName="btn-primary">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<input type="submit" value="Upload File" class="btn btn-primary" />
</div>
</div>
</div>
</form>
Controller logic
[HttpPost]
public async Task<IActionResult> Upload(ICollection<IFormFile> files)
{
if (await _contextPB.UploadRow.AnyAsync())
{
Danger(string.Format("Please LOAD the existing containers before uploading another file"), true);
return View();
}
int rowCount = 0;
var uploads = Path.Combine(_environment.WebRootPath, "uploads");
var _viewModel = new UploadViewModel();
foreach (var file in files)
{
using (var streamReader = System.IO.File.OpenText(Path.Combine(uploads, file.FileName)))
{
var line = streamReader.ReadLine();
var columnNames = line.Split(new[] { ',' });
if (!ValidateColumnNames(columnNames))
{
Danger(string.Format("Invalid Column Name in Upload file"), true);
return View(_viewModel);
}
while (!streamReader.EndOfStream)
{
var data = line.Split(new[] { ',' });
var uploadRow = new UploadRow();
// validation & assignment logic removed
try
{
_contextPB.Add(uploadRow);
rowCount++;
}
catch (Exception e)
{
Danger(string.Format("<b>{0},{1}</b> database error", uploadRow.Container_Id, e), true);
}
line = streamReader.ReadLine();
}
}
}
}
Try adding a catch block to see what the error is.
I'm assuming a permission issue.
[HttpPost]
public async Task<IActionResult> Upload(ICollection<IFormFile> files)
{
try
{
if (await _contextPB.UploadRow.AnyAsync())
{
Danger(string.Format("Please LOAD the existing containers before uploading another file"), true);
return View();
}
// your code
}
catch (Exception ex)
{
// what is the error?
// add a breakpoint to see
throw;
}
}
Related
at this moment I am uploading any file and saving it. What I want is to generate an error message if the user does not select any file and press the upload button, but at this moment the only thing it does is redirect to another view whether or not it has selected files. I would like to know if there is another better way to generate the upload of these files
this is my controller
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
[HttpPost]
public void Upload(HttpPostedFileBase file)
{
string file = (file.FileName).ToLower();
try
{
file.SaveAs(Server.MapPath("~/Uploads/" + file));
}
catch (Exception e)
{
ViewBag.UploadError = "Upload file error";
}
}
}
this is the view:
#{
ViewBag.Title = "Home";
}
#using (Html.BeginForm("Transformation", "Xml", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="col-md-12 offset-md-5">
<div class="custom-file col col-lg-2">
<input type="file" name="file" class="custom-file-input" id="inputGroupFile01" aria-describedby="inputGroupFileAddon01">
<label class="custom-file-label" for="inputGroupFile01">Choose file</label>
</div>
<div class="col-5">
<button class="btn btn-success col-md-4 mt-2" type="submit">Upload file</button>
</div>
</div>
//Message Error
<div class="alert alert-danger" role="alert">
<p class="text-danger">
#ViewBag.UploadError
</p>
</div>
}
#Thomas Caycedo Martinez, I believe you can simply modify your controller method like below.
If error, return to the same view with an error message.
Your view remains unchanged.
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if (file != null)
{
string fileName = (file.FileName).ToLower();
try
{
file.SaveAs(Server.MapPath("~/Uploads/" + fileName));
}
catch (Exception e)
{
ViewBag.UploadError = "Upload file error";
return View("Index");
}
}
else {
ViewBag.UploadError = "Upload file error";
return View("Index");
}
return View();
}
write the action and controller correctly
#using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
and check file in action
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if( file != null && file.Length > 0)
{
string file = (file.FileName).ToLower();
try
{
file.SaveAs(Server.MapPath("~/Uploads/" + file));
}
catch (Exception e)
{
ViewBag.UploadError = "Upload file error";
}
return View("Index");
}
else
{
//do something
return View("Index");
}
}
You can use JavaScript/JQuery to check for the same..
$(function(){
$("#btnSubmit").on("click",function(){
if($("#inputGroupFile01").val()==""){
alert("Please select a file")
return false;
}
})
})
where btnSubmit is the id for the submit button
I use asp.net core razor pages to create my application, in my create page, I have two file controls, one for upload icon image and the other for uploading detail images. But when I click edit button, all of the fields were initialized, except the two file controls. Please check my code. Anyone can help?
In my razor page:
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label asp-for="Product.Icon" class="control-label"></label>
<input asp-for="#Model.Icon" type="file" />
<span asp-validation-for="Product.Icon" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="control-label”>Detail Images(support multi-uploading):</label>
<input type="file" id="fUpload" name="files" multiple />
</div>
</div>
</div>
In my page model:
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Product = await _context.Products
.Include(p => p.Shop).SingleOrDefaultAsync(m => m.ID == id);
if (Product == null)
{
return NotFound();
}
ViewData["Shop"] = new SelectList(_context.Shops, "ID", "Name");
return Page();
}
public async Task<IActionResult> OnPostAsync(List<IFormFile> files)
{
if (!ModelState.IsValid)
{
return Page();
}
var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
if (!Directory.Exists(uploads))
{
Directory.CreateDirectory(uploads);
}
if (this.Icon != null)
{
var fileName = GetUniqueName(this.Icon.FileName);
var filePath = Path.Combine(uploads, fileName);
this.Icon.CopyTo(new FileStream(filePath, FileMode.Create));
this.Product.Icon = fileName;
}
if (files != null && files.Count > 0)
{
foreach (IFormFile item in files)
{
if (item.Length > 0)
{
var fn = GetUniqueName(item.FileName);
var fp = Path.Combine(uploads, fn);
item.CopyTo(new FileStream(fp, FileMode.Create));
this.Product.ProductImages = this.Product.ProductImages + fn + "^";
}
}
}
_context.Attach(Product).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(Product.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
The most important part of your page is missing from the code you provided - the <form> tag. For file uploading to work, you must specify that the method is post and you must also provide an enctype attribute with its value set to multipart/form-data:
<form method="post" enctype="multipart/form-data">
...
Ref: https://www.learnrazorpages.com/razor-pages/forms/file-upload
I'm developing a system in .NET and I need to send a json controller msg to the view and show it in modal.
The user will import a spreadsheet and the spreadsheet will be inserted in the database, at the end of the modal it should appear with the message whether it was sent or not.
Or backend is already working.
I need help on the front because when I import, it loads a new page with
["Sent with success"]
(the messages are in portuguese) = ["Enviado com sucesso"]
Follows the controller code.
public JsonResult UploadExcel(HttpPostedFileBase FileUpload)
{
List<string> data = new List<string>();
if (FileUpload != null)
{
// tdata.ExecuteCommand("truncate table OtherCompanyAssets");
if (FileUpload.ContentType == "application/vnd.ms-excel" || FileUpload.ContentType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
string filename = FileUpload.FileName;
string targetpath = "C:/Users/70561/Documents";
FileUpload.SaveAs(targetpath + filename);
string pathToExcelFile = targetpath + filename;
var connectionString = "";
if (filename.EndsWith(".xls"))
{
connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=Excel 8.0;", pathToExcelFile);
}
else if (filename.EndsWith(".xlsx"))
{
connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\";", pathToExcelFile);
}
var adapter = new OleDbDataAdapter("SELECT * FROM [Planilha1$]", connectionString);
var ds = new DataSet();
adapter.Fill(ds, "ExcelTable");
DataTable dtable = ds.Tables["ExcelTable"];
string sheetName = "Planilha1";
var excelFile = new ExcelQueryFactory(pathToExcelFile);
var dados = from a in excelFile.Worksheet<RETORNO_CM>(sheetName) select a;
foreach (var a in dados)
{
try
{
if (a.CM_CODIGO != null && a.CM_QM_COMPONENTE_RMA != null && a.CM_NS != null && a.CM_DESCRICAO != null &&
a.CM_DEFEITO != null && a.J_FALHA != null &&
a.CM_TIPO_DEFEITO != null && a.J_PLACA_RETRABALHO != null &&
a.J_PLACA_RESTESTADA != null && a.J_STATUS != null && a.CM_NOME_TESTE != null && a.CM_NOME_DEBUG != null)
{
RETORNO_CM CM = new RETORNO_CM();
CM.CM_CODIGO = a.CM_CODIGO;
CM.CM_QM_COMPONENTE_RMA = a.CM_QM_COMPONENTE_RMA;
CM.CM_NS = a.CM_NS;
CM.CM_DESCRICAO = a.CM_DESCRICAO;
CM.CM_DATA_REPARO = a.CM_DATA_REPARO;
CM.CM_DEFEITO = a.CM_DEFEITO;
CM.J_FALHA = a.J_FALHA;
CM.CM_TIPO_DEFEITO = a.CM_TIPO_DEFEITO;
CM.CM_COMPONENTE = a.CM_COMPONENTE;
CM.J_PLACA_RETRABALHO = a.J_PLACA_RETRABALHO;
CM.J_PLACA_RESTESTADA = a.J_PLACA_RESTESTADA;
CM.J_STATUS = a.J_STATUS;
CM.CM_NOME_TESTE = a.CM_NOME_TESTE;
CM.CM_NOME_DEBUG = a.CM_NOME_DEBUG;
db.RETORNO_CM.Add(CM);
db.SaveChanges();
}
else
{
data.Add("<ul>");
data.Add("</ul>");
data.ToArray();
return Json(data, JsonRequestBehavior.AllowGet);
}
}
catch (DbEntityValidationException ex)
{
foreach (var entityValidationErrors in ex.EntityValidationErrors)
{
foreach (var validationError in entityValidationErrors.ValidationErrors)
{
Response.Write("Property: " + validationError.PropertyName + " Error: " + validationError.ErrorMessage);
}
}
}
}
//deleting excel file from folder
if ((System.IO.File.Exists(pathToExcelFile)))
{
System.IO.File.Delete(pathToExcelFile);
}
data.Add("Enviado com sucesso");
return Json(data, JsonRequestBehavior.AllowGet);
}
else
{
//alert message for invalid file format
data.Add("Apenas arquivos excel sao suportados");
return Json(data, JsonRequestBehavior.AllowGet);
}
}
else
{
if (FileUpload == null) data.Add("Selecione um arquivo");
return Json(data, JsonRequestBehavior.AllowGet);
}
}
my view code
<div class="box">
<div class="box-body">
<hr />
<article class="table-responsive" style="overflow:hidden">
<p class="lead">Teste de importação.</p>
<hr />
#using (Html.BeginForm("UploadExcel", "RetornoCM", FormMethod.Post, new { enctype = "multipart/form-data", onsubmit = "return myFunction()" }))
{
<div class="form-horizontal">
<div class="form-group">
<div class="control-label col-md-2">Escolha o Arquivo:</div>
<div class="col-md-10">
<input type="file" id="FileUpload" name="FileUpload" class="" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Enviar" id="btnSubmit" class="btn btn-primary" />
</div>
</div>
</div>
}
<div class="modal fade" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>
<b>Message:</b><br>
<input class="message-edit-text" type="text" size="20">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</article>
</div>
You should not return JSON, as you are performing a full page postback. Instead, you should return a View.
If you do not want to perform a full page postback, you want to use Ajax since the beginning of the request.
For example,
View
Please make sure button is type="button" to avoid full page postback.
#using (Html.BeginForm("UploadExcel", "RetornoCM", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-horizontal">
<div class="form-group">
<div class="control-label col-md-2">Escolha o Arquivo:</div>
<div class="col-md-10">
<input type="file" id="FileUpload" name="FileUpload" class="" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="button" id="btnSubmit" class="btn btn-primary">
Enviar
</button>
</div>
</div>
</div>
}
<script>
$(function () {
$('#btnSubmit').click(function() {
// Checking whether FormData is available in browser
if (window.FormData !== undefined) {
var fileUpload = $("#FileUpload").get(0);
var files = fileUpload.files;
// Create FormData object
var fileData = new FormData();
// Looping over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
$.ajax({
url: '#Url.Action("UploadExcel", "RetornoCM")',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fileData,
success: function(result) {
alert(result);
},
error: function(err) {
alert(err.statusText);
}
});
}
});
});
</script>
Action Method
[HttpPost]
public ActionResult UploadExcel()
{
if (Request.Files.Count > 0)
{
try
{
HttpFileCollectionBase files = Request.Files;
for (int i = 0; i < files.Count; i++)
{
HttpPostedFileBase file = files[i];
// Do somethig with file
}
return Json("File Uploaded Successfully!");
}
catch (Exception ex)
{
return Json("Error occurred. Error details: " + ex.Message);
}
}
else
{
return Json("No files selected.");
}
}
Source: File Upload Through JQuery AJAX In ASP.NET MVC
I have an Angular application, written in Typescript, with an ASP.Net Web Api backend. I am trying to use the ng-file-upload (see this link for details) directive to upload an image file.
I receive an exception in my Web API Post method:
"Unexpected end of MIME multipart stream. MIME multipart message is not complete."
I've done my research and found similar issues here - I have tried to implement Landuber Kassa's answer but without success.
Also this although my project is not MVC and in any case it did not work.
I am fresh out of ideas and would appreciate the community's thoughts. I am happy to consider any other alternatives if I can be pointed in the right direction.
Ash
My .Net Post method (implementing Landuber Kassa's idea):
[RoutePrefix("BeaufortAppStore/api/Image")]
public class ImageController : ApiController
{
#region Methods
#region Posts
[Route("UploadImage")]
[HttpPost]
public async Task<IHttpActionResult> UploadImage()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var provider = new MultipartMemoryStreamProvider();
Stream reqStream = Request.Content.ReadAsStreamAsync().Result;
MemoryStream tempStream = new MemoryStream();
reqStream.CopyTo(tempStream);
tempStream.Seek(0, SeekOrigin.End);
StreamWriter writer = new StreamWriter(tempStream);
writer.WriteLine();
writer.Flush();
tempStream.Position = 0;
StreamContent streamContent = new StreamContent(tempStream);
foreach (var header in Request.Content.Headers)
{
streamContent.Headers.Add(header.Key, header.Value);
}
// Read the form data and return an async task.
await streamContent.ReadAsMultipartAsync(provider); // FAILS AT THIS POINT
foreach (var file in provider.Contents)
{
var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
var buffer = await file.ReadAsByteArrayAsync();
//Do whatever you want with filename and its binary data.
}
return Ok();
}
#endregion
#endregion
My angular controller method:
public upload(): void {
//Create config used in ng-file-upload
var config: IFileUploadConfigFile = {
data: this.file, url: "BeaufortAppStore/api/Image/UploadImage/", method: "POST" };
this._dataService.uploadImage(config).then((result: any) => {
this.thumbnail = result.data;
});
}
My angular view (partial view for a directive):
<div class="form-group">
<label for="file" class="control-label col-xs-2">Choose a file</label>
<input id="file" type="file" name="file" class="form-control" ngf-select ngf-pattern="'image/*'"
ng-model="vm.file" />
<img style="width:100px;" ngf-thumbnail="thumbnail || '/thumb.jpg'" />
<button type="submit" ng-click="vm.upload()">Upload</button>
Try this in C#:
[HttpPost]
[Route("Profile/Image")]
public Task<HttpResponseMessage> UploadImgProfile()
{
try
{
if (!ModelState.IsValid) return null;
var currentUser = _userUtils.GetCurrentUser(User);
if (currentUser == null) return null;
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType));
string root = HttpContext.Current.Server.MapPath("~" + Constant.Application.User_Image_Directory);
bool exists = Directory.Exists(root);
if (!exists)
Directory.CreateDirectory(root);
var provider = new MultipartFormDataStreamProvider(root);
var task = request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
var finfo = new FileInfo(provider.FileData.First().LocalFileName);
string guid = Guid.NewGuid().ToString();
var fileName = guid + "_" + currentUser.IdOwin + ".jpg";
File.Move(finfo.FullName, Path.Combine(root, fileName));
return new HttpResponseMessage()
{
Content = new StringContent(Path.Combine(Constant.Application.User_Image_Directory, fileName))
};
}
);
return task;
}
catch (Exception ex)
{
_logger.LogException(ex);
return null;
}
}
Angular Controller:
//Upload Func
$scope.upload = function (files) {
if (files && files.length) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
$scope.uploading = true;
// $scope.imageName = file.name;
$upload.upload({
url: enviroment.apiUrl + '/api/CurrentUser/Profile/Image',
//fields: { 'username': $scope.username },
file: file
}).progress(function (evt) {
$scope.uploading = true;
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
$scope.progress = progressPercentage;
}).success(function (data, status, headers, config) {
console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
$scope.imageName = data;
$scope.uploading = false;
$scope.loadSuccess = true;
vm.uploadImage = false;
//AR
var reader = new FileReader();
reader.onload = function (evt) {
$scope.$apply(function ($scope) {
$scope.myImage = evt.currentTarget.result;
});
};
reader.readAsDataURL(files[0]);
//END AR
});
}
}
};
// Stay on Listen upload file
$scope.$watch('files', function (evt) {
$scope.upload($scope.files);
});
HTML:
<div class="row">
<!--UPLOAD-->
<div class="up-buttons">
<div class="clearfix visible-xs-block"></div>
<div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center box-upload-image" data-ng-show="profileCtrl.uploadImage">
<br />
<div id="imgDragDrop" ng-file-drop ng-model="files"
drag-over-class="dragover"
accept="image/*">
<div class="cropArea-bkg">
<h4>
<span class="mdi mdi-account mdi-48px"></span>
<br /><br />
Carica immagine profilo
</h4>
<p>Trascina qui la tua immagine, oppure</p>
<div ng-file-select="" ng-model="files" class="btn btn-secondary" ng-accept="'*.pdf,*.jpg,*.png'" tabindex="0">
Sfoglia sul tuo computer
</div><br>
</div>
</div>
<div ng-no-file-drop class="well bg-danger">File Drag/Drop non è supportato da questo browser</div>
<br />
<div class="text-center">
<div class="progress" ng-show="uploading">
<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="{{ ::progress }}" aria-valuemin="0" aria-valuemax="100" style="width: {{::progress}}% ">
<span class="sr-only">{{ ::progress }}% Complete</span>
</div>
</div>
</div>
</div>
<!--END UPLOAD-->
</div>
</div>
This is a part of my view code for Index action of Manage Controller.
<div class="mngimg">
#using (Html.BeginForm("UploadPhoto", "Manage", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="btn btn-default browseimg">
<input type="file" name="file" id="files" onchange="this.form.submit()" />
</div>
<div class="btn btn-default browseimg">
#Html.ActionLink("Remove Photo", "RemovePhoto", "Manage")
</div>
}
</div>
</div>
}
</dd>
<dt>Password:</dt>
<dd>
[
#if (Model.HasPassword) <!-- Here is my error. The Model is null -->
{
#Html.ActionLink("Change your password", "ChangePassword")
}
else
{
#Html.ActionLink("Create", "SetPassword")
}
]
</dd>
Whenever I open this page and click "Remove Photo" I keep getting an error saying that An exception of type 'System.NullReferenceException' occurred in App_Web_ckoryptg.dll but was not handled in user code. I tried debugging, but I am unable to figure out why my Model.HasPassword is becoming null. Here is my RemovePhoto Action from Manage Controller.
[HttpPost]
public async Task<ActionResult> UploadPhoto(HttpPostedFileBase file)
{
if (file != null && file.ContentLength > 0)
{
var user = await GetCurrentUserAsync();
var userId = user.Id;
var fileExt = Path.GetExtension(file.FileName);
var fnm = userId + ".png";
if (fileExt.ToLower().EndsWith(".png") || fileExt.ToLower().EndsWith(".jpg") || fileExt.ToLower().EndsWith(".gif"))// Important for security if saving in webroot
{
var filePath = HostingEnvironment.MapPath("~/Content/Images/") + fnm;
var directory = new DirectoryInfo(HostingEnvironment.MapPath("~/Content/Images/"));
if (directory.Exists == false)
{
directory.Create();
}
ViewBag.FilePath = filePath.ToString();
file.SaveAs(filePath);
return RedirectToAction("Index", new { Message = ManageMessageId.PhotoUploadSuccess });
}
else
{
return RedirectToAction("Index", new { Message = ManageMessageId.FileExtensionError });
}
}
return RedirectToAction("Index", new { Message = ManageMessageId.Error });// PRG
}
private async Task<ApplicationUser> GetCurrentUserAsync()
{
return await UserManager.FindByIdAsync(User.Identity.GetUserId());
}
I opened a default MVC project that comes with visual studio and I added these extra things that I followed from this tutorial ASP.NET upload images. How do I resolve this?
Edit:
This is my RemovePhoto action.
public ActionResult RemovePhoto()
{
string file = "~/Content/Images/" + User.Identity.GetUserId() + ".png";
if(System.IO.File.Exists(Server.MapPath(file)))
System.IO.File.Delete(Server.MapPath(file));
return View("Index");
}
Just Redirect back to your Index action. That way you don't have to instantiate your Index model in your RemovePhoto action. Can read more about this pattern here.