Hello i have button and when i click it this function is called :
public async Task<IActionResult> QrCode(int Id)
{
var model = await context.Files.Where(x => x.Id == Id).FirstOrDefaultAsync();
string qrUrl = CreateQrLink(Id);
FileDetailsViewModel fileDetails = new FileDetailsViewModel
{
Id = model.Id,
Name = model.Name,
Author=model.Author,
Description=model.Description,
Genre=model.Genre,
PublishedOn = model.PublishedOn,
QrUrl = qrUrl
};
return View(fileDetails);
}
Here is CreateQrLink function
public string CreateQrLink(int Id)
{
var baseUrl = string.Format("{0}://{1}{2}",Request.Scheme, Request.Host, Url.Content("~"));
QRCodeGenerator QrGenerator = new QRCodeGenerator();
var url = Url.Action("DownloadFileFromFileSystem", "Files", new { id = Id });
QRCodeData QrCodeInfo = QrGenerator.CreateQrCode(baseUrl+url, QRCodeGenerator.ECCLevel.Q);
QRCode QrCode = new QRCode(QrCodeInfo);
Bitmap QrBitmap = QrCode.GetGraphic(60);
byte[] BitmapArray;
using(MemoryStream ms = new MemoryStream())
{
QrBitmap.Save(ms, ImageFormat.Png);
BitmapArray = ms.ToArray();
}
string qrUri= string.Format("data:image/png;base64,{0}", Convert.ToBase64String(BitmapArray));
return qrUri;
}
And Here is View i want to download Image from this view with clicking Download QrCode button,how i can implement it ? I dont save QrLink in database should i save it or something else ? I want to fetch photo from src=Model.QrUrl
#model FileDetailsViewModel
#{
ViewBag.Title = "Qr Code";
}
<div class="row justify-content-center m-3">
<div class="col-sm-8">
<div class="card">
<div class="card-header">
<h1>#Model.Name</h1>
<h2>Product Id: #Model.Id</h2>
</div>
<div class="card-body text-center">
<img style="width:450px;height:450px;" src="#Model.QrUrl" />
</div>
<div class="card-footer text-center">
<a asp-controller="files" asp-action="Details" asp-route-id="#Model.Id" class="btn btn-primary">Back</a>
Download QrCode
</div>
</div>
</div>
</div>
Your returning type should be of FileResult as follow i.e.
string filePath = string.Format("data:image/png;base64,{0}", Convert.ToBase64String(BitmapArray))
string contentType = ImageFormat.Png.ToString();
FileResult qrUri= this.File(filePath, contentType);
return qrUri;
Here is solution just simple add download = "Name for downloaded file" href="url of the image"
<a download="#Model.Name" style="width:150px;" href="#Model.QrUrl"class="btn btn-success">Download</a>
Related
I have the following application, where I have to upload an image directly from modal to the page.
Note that:
The image is already uploaded by the admin to this modal.
The images are saved in "static" file in "wwwroot" folder. So, No database is required for this step.
All what I need is when I click in the image in the modal, it should be uploaded to the view. So, I can save it later in the database.
Here is Image Bank Controller
public IActionResult Index()
{
var webRoot = _hostingEnvironment.WebRootPath;
var appData = System.IO.Path.Combine(webRoot, "static");
var files = Directory.GetFiles(appData, "*.*", SearchOption.AllDirectories);
var model = new ImageBankViewModel()
{
ImagesListUrls = files.Select(i=>Path.GetFileName(i))
};
return View(model);
}
[HttpPost]
public IActionResult Upload(ImageBankViewModel model)
{
if (ModelState.IsValid)
{
if (model.Image != null)
{
string webRootPath = _hostingEnvironment.WebRootPath;
var path = Path.Combine(webRootPath, "static");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
var extension = Path.GetExtension(model.Image.FileName);
var newFileName = model.Type + "-" + DateTime.Now.Ticks;
using (var filesStream = new FileStream(Path.Combine(path, newFileName + extension), FileMode.Create))
{
model.Image.CopyTo(filesStream);
}
return RedirectToAction("Index");
}
}
ImageBankViewModel modelVM = new ImageBankViewModel()
{
Image = model.Image,
ImagesListUrls = model.ImagesListUrls,
Type = model.Type
};
return RedirectToAction("Index",modelVM);//Unsuccessful Upload , fix invalid model
}
public IActionResult CreateStory()
{
return View();
}
public ActionResult GetImagesPartial()
{
var webRoot = _hostingEnvironment.WebRootPath;
var appData = System.IO.Path.Combine(webRoot, "static");
var files = Directory.GetFiles(appData, "*.*", SearchOption.AllDirectories);
var model = new ImageBankViewModel()
{
ImagesListUrls = files.Select(i => Path.GetFileName(i))
};
return PartialView("_ImagesBankModal",model);
}
public void ImageDelete(string image)
{
}
public void SelectImage(string image)
{
// Here I want to get the selected image from the modal
}
}
}
Create Story View
#{
ViewData["Title"] = "CreateStory";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>CreateStory</h1>
<div class="row">
<div class="col-md-1">
<label>Pic1</label>
</div>
<div class="col-md-8">
<input type="file" accept="image/*" class="form-control" />
</div>
<div class="col-md-3">
<a class="btn btn-outline-dark" asp-area="" asp-controller="Bank" asp-action="GetImagesPartial" data-toggle="modal" data-target="#myModal" id="sel">Select from image bank</a>
<div class="modal" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div id="partial"></div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-1">
<label>Pic2</label>
</div>
<div class="col-md-8">
<input type="file" accept="image/*" class="form-control" />
</div>
<div class="col-md-3">
<button class="btn btn-outline-dark">Select from image bank</button>
</div>
</div>
#section Scripts{
<script type="text/javascript">
$(function () {
$('#sel').click(function () {
var route = '#Url.Action("GetImagesPartial", "Bank")';
$('#partial').load(route);
});
});
</script>
}
Modal Partial View
#model TestApplication.Models.ViewModels.ImageBankViewModel
<div class="modal-header">
<h2 class="modal-title">Choose</h2>
</div>
<div class="modal-body">
#if (Model.ImagesListUrls.Any())
{
<table>
#foreach (var image in Model.ImagesListUrls)
{
<tr>
<td>
<a asp-area="" asp-controller="Bank" asp-action="SelectImage" asp-route-image="#image" class="btn btn-light position-absolute" style="right:0">Select</a>
<img src="~/static/#image" class="img-thumbnail" />
</td>
</tr>
}
</table>
}
else
{
<h5>no images exists...</h5>
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success" data-dismiss="modal">Cancel</button>
</div>
You can store the relative path of the selected picture in an input and pass them to the action.
The following is an example, you can refer to it.
Index
<form asp-action="Upload" asp-controller="ImageBank" method="post" enctype="multipart/form-data">
<div class="row">
<div class="col-md-1">
<label>Pic1</label>
</div>
<div class="col-md-8">
<input type="file" accept="image/*" class="form-control" name="model.Image"/>
<ul class="selectedpic">
</ul>
</div>
<div class="col-md-3">
<a class="btn btn-outline-dark sel">Select from image bank</a>
</div>
<div class="col-md-8 addedimg">
</div>
</div>
<div class="modal" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div id="partial"></div>
</div>
</div>
</div>
<button type="submit">submit</button>
</form>
#section Scripts{
<script type="text/javascript">
var currentsel="";
$('body').on("click",".sel",function () {
localStorage.setItem("currentsel",$(this).attr("class"));
var route = '#Url.Action("GetImagesPartial", "ImageBank")';
$("#myModal").modal("show");
$('#partial').load(route);
});
$('body').on("click",".selectbtn",function () {
var currenttd=$(this).closest("td");
console.log(currenttd.find("img").attr("src"))
var classarry=localStorage.getItem("currentsel").split(" ");
var currentsel="."+classarry[classarry.length-1];
var currentaddedimg=$(currentsel).closest(".row").find(".addedimg");
var addsrc=currenttd.find("img").attr("src");
if(checkisexsist(currentaddedimg,addsrc)){
$(currentsel).closest(".row").find(".selectedpic").append("<li>"+addsrc+"</li>");
$(currentsel).closest(".row").find(".addedimg").append("<input hidden name='selimages' value='"+addsrc+"'/>");
$("#myModal").modal("hide");
$('#myModal').on('hidden.bs.modal', function (e) {
localStorage.removeItem("currentsel");
});
}else{
alert("has selected");
}
});
function checkisexsist(currentaddedimg,addsrc){
var flag=true;
$.each(currentaddedimg.find("input[name='selimages']"), function( index, value ) {
if($(value).val()==addsrc){
flag=false;
}
});
return flag;
}
</script>
}
Controller
[HttpPost]
public IActionResult Upload(ImageBankViewModel model,List<string> selimages)
{
if (ModelState.IsValid)
{
if (model.Image != null)
{
string webRootPath = _hostingEnvironment.WebRootPath;
var path =Path.Combine(webRootPath, "static");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
var extension = Path.GetExtension(model.Image.FileName);
var newFileName = model.Type + "-" + DateTime.Now.Ticks;
using (var filesStream = new FileStream(Path.Combine(path, newFileName + extension), FileMode.Create))
{
model.Image.CopyTo(filesStream);
}
}
if(selimages!=null& selimages.Count != 0)
{
string webRootPath = _hostingEnvironment.WebRootPath;
var path = Path.Combine(webRootPath, "static");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
selimages.ForEach(m =>
{
var newFileName = Guid.NewGuid().ToString();
var extension = "." + m.Split(".")[m.Split(".").Length - 1];
var oldpath =webRootPath+m.Replace("/", "\\"); var newpath = Path.Combine(path, newFileName + extension);
System.IO.File.Copy(oldpath,newpath);
});
}
return RedirectToAction("Index");
}
ImageBankViewModel modelVM = new ImageBankViewModel()
{
Image = model.Image,
ImagesListUrls = model.ImagesListUrls,
Type = model.Type
};
return RedirectToAction("Index", modelVM);//Unsuccessful Upload , fix invalid model
}
_ImagesBankModal(Only give the modified place)
<a class="btn btn-light position-absolute selectbtn">Select</a>
Result
I want to insert multiple Image to the folder and path and also some data to database in ASP.net MVC.
Action
[HttpPost]
public ActionResult SaveProduct(ProductViewModel model, IEnumerable<HttpPostedFileBase> file)
{
try
{
Product pvm = new Product();
string upload = string.Empty;
foreach (var item in file)
{
string filename = Guid.NewGuid() + Path.GetExtension(item.FileName);
string filepath = "~/Images/" + filename;
item.SaveAs(Path.Combine(Server.MapPath("~/Images"), filename));
upload += filepath + ":";
}
string[] patharray = upload.Split(':');
pvm.product_name = model.product_name;
pvm.product_description = model.product_description;
pvm.is_new = model.is_new;
pvm.is_discount = null;
pvm.new_price = model.new_price;
pvm.old_price = model.old_price;
pvm.img1 = patharray[0].ToString();
pvm.img2 = patharray[1].ToString();
pvm.img3 = patharray[2].ToString();
pvm.img4 = patharray[3].ToString();
pvm.category = null;
pvm.quantity = model.quantity;
pvm.offer_title = null;
pvm.star = null;
pvm.CategoryID = model.CategoryID;
pvm.SubCategoryID = model.SubCategoryID;
db.Products.Add(pvm);
db.SaveChanges();
Console.WriteLine(pvm.ToString());
}
return RedirectToAction("AddProduct");
}
View
<form class="form-inline">
#using (Html.BeginForm("SaveProduct", "AdminSide", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="col-md-10"><input type="file" name="file" /></div>
<div class="col-md-10"><input type="file" name="file" /></div>
<div class="col-md-10"><input type="file" name="file" /></div>
<div class="col-md-10"><input type="file" name="file" /></div>
<input type="submit" value="Save" class="btn btn-block btn-primary" />
}
</form>
I am trying to save data and edit that data using the button with Id btnSaveAnContinue. Now, whenever I click on Save And Continue button to save data, the command parameter in post method i.e gets Saveandcontinue which is defined in the button as per required.
But whenever, I try to edit the data and save it by clicking on same button, the command parameter in AddEdit POST method does not get Saveandcontinue, it is null.
The View:
<form asp-controller="Doctor" asp-action="AddEdit" method="post" class="form-horizontal" id="DoctorAddEdit" role="form">
#Html.HiddenFor(c => c.DoctorId)
<div class="m-b-md heading-tp-cls">
<h3 class="m-b-none pull-left">Doctor Information <small id="currentUsersInCase"></small></h3>
<div class="doc-buttons pull-right relative">
<button type="submit" class="btn btn-s-md btn-success saveButton" id="btnSave"><i class="fa fa-save fa-fw"></i>Save And Close</button>
<button type="submit" name="command" value="Saveandcontinue" id="btnSaveAnContinue" class="btn btn-s-md btn-success saveButton "><i class="fa fa-save fa-fw"></i>Save And Continue</button>
</div>
<div class="clearfix"></div>
</div>
<section class="panel panel-default tp-section-cls no-left-right-borders" style="padding-top: 10px;">
<div class="row m-l-none m-r-none bg-light lter">
<section>
<div class="col-lg-2 col-md-2 col-sm-6 error-holder-form hideSubject" id="claimanatFirstNameDiv">
<label>First Name<span class="requAstrik">*</span></label>
<input asp-for="FirstName" id="DFirstName" class="form-control subjectHide" placeholder="" type="text">
<span asp-validation-for="FirstName" class="text-danger error"></span>
</div>
<div class="col-lg-2 col-md-2 col-sm-6 hideSubject" id="claimanatMiddleInitialDiv">
<label>Middle Name</label>
<input asp-for="MiddleInitial" id="DMidName" class="form-control subjectHide" placeholder="" type="text">
</div>
</section>
</div>
</section>
</form>
GET method for AddEdit:
public IActionResult AddEdit(int id = 0, bool flag = false)
{
var getDoctorById = _doctorService.GetDoctorInfoById(id);
return View(getDoctorById);
}
POST method for AddEdit:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddEdit(DoctorInfoModel doctorInfo, string command)
{
bool isAjaxCall = HttpContext.Request.Headers["x-requested-with"] == "XMLHttpRequest";
if (isAjaxCall)
{
return Content("Saved");
}
if (ModelState.IsValid)
{
var result = 0;
int userId = User.GetUserId();
doctorInfo.CreatedBy = userId;
var saveAndGetUserId = 0;
if (doctorInfo.DoctorId == 0)
{
saveAndGetUserId = _doctorService.SaveUserInfo(doctorInfo);
var user = new ApplicationUser { UserName = doctorInfo.UserName, Email = doctorInfo.DocEmail, UserId = saveAndGetUserId };
var getResult = await _userManager.CreateAsync(user, doctorInfo.Password);
_doctorService.SaveUserRole(user.Id);
}
else
{
var getUserId = _doctorService.GetUser(doctorInfo);
var user = _userManager.Users.FirstOrDefault(c => c.UserId == getUserId);
user.UserName = doctorInfo.UserName;
user.Email = doctorInfo.DocEmail;
if (doctorInfo.Password != null && !"Password#123".Equals(doctorInfo.Password))
{
user.PasswordHash = _userManager.PasswordHasher.HashPassword(user, doctorInfo.Password);
}
try
{
var result1 = await _userManager.UpdateAsync(user);
}
catch (Exception ex)
{
throw;
}
}
var getSaveResult = _doctorService.SaveDoctor(doctorInfo, saveAndGetUserId);
if (getSaveResult.Id > 0)
{
Success(getSaveResult.MessageBody);
}
else
{
Warning(getSaveResult.MessageBody);
}
if (command == "Saveandcontinue")
{
return RedirectToAction(nameof(DoctorController.AddEdit), new { id = getSaveResult.Id, flag = true });
}
else
{
return RedirectToAction(nameof(HomeController.Index), "Doctor");
}
}
Warning("Failed to save Doctor, try again later.");
return View("AddEdit", doctorInfo);
}
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>