Reading and Displaying Uploaded text Files in MVC - asp.net-mvc

Is it possible to read uploaded text files e.g .txt and display the content in a textbox ? I want to do a file conversion of the uploaded files. I've managed to upload and validate the files I would like at the click of a button to read the contents and display them in a textbox ready for conversion. How would I go about doing this?
Upload class
public class UploadedFile
{
public long Size { get; set; }
public string Path { get; set; }
public string Name { get; set; }
// public int Length { get; set; }
public string extension { get; set; }
}
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
var supportedTypes = new[] { "txt", "rtf", "html", "xaml", "xslx" ,"pdf", "doc", "docx", "csv" };
var fileExt = System.IO.Path.GetExtension(file.FileName).Substring(1);
if (!supportedTypes.Contains(fileExt))
{
ModelState.AddModelError("file", "Invalid type. Only the following types (txt, rtf, html, xslx, pdf, xaml, doc, docx, csv) are supported.");
return View();
}
if (file.ContentLength > 200000)
{
ModelState.AddModelError("file", "The size of the file should not exceed 200 KB");
return View();
}
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/uploads"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
public ActionResult About()
{
var uploadedFiles = new List<UploadedFile>();
var files = Directory.GetFiles(Server.MapPath("~/uploads"));
foreach(var file in files)
{
var fileInfo = new FileInfo(file);
var uploadedFile = new UploadedFile() {Name = Path.GetFileName(file)};
uploadedFile.Size = fileInfo.Length;
uploadedFile.extension = Path.GetExtension(file);
uploadedFile.Path = ("~/uploads/") + Path.GetFileName(file);
uploadedFiles.Add(uploadedFile);
}
return View(uploadedFiles);
}
}
So far the files uploaded are listed in a table.I would like to read and display the contents if the button is Clicked and the contents placed inside the text area below the table. So I can perform conversion.
How would I achieve this? Thanks
`<script>$('btnreadfile').click(function () {
document.location = '#Url.Action("ReadTextFile","Home")'; });</script>
<input id="btnreadfile" name="btnReadFile" type="submit" value="Read File"/>
`My button Code

Working code. Fully tested
in you _Layout.cshtml
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
</head>
in your About.cshtml
Table mark up
<table style="background-color: lightgreen; border: solid 2px black;">
<tr>
<td>
<b>Name</b>
</td>
<td>
<b>Size</b>
</td>
<td>
<b>Preview</b>
</td>
<td>
<b>Read File</b>
</td>
</tr>
#foreach (var file in Model)
{
<tr>
<td>
#file.Name
</td>
<td>
#(file.Size / 1000) KB
</td>
<td>
#(file.extension)
</td>
<td>
<input id="btnreadfile" name="#file.Name" class='btnClick' type="button" value="Read File"/>
<textarea rows="4" cols="50">
</textarea>
</td>
</tr>
}
</table>
in your About.cshtml all the way bottom add this script
<script>
$.ajax({
url: "/Home/ReadTextFile",
type: "GET",
data: { fileName: $(this).attr("name") },
DataType: "text",
success: function (str) {
alert(str);
$("textarea").val(str); // this line has to be replaced with more dynamic jQuery selector that can select this button next textarea
//$(this).next("textarea").val(str);
},
error: function (err) {
alert(err);
}
});
});
</script>
in Your Controller
Add reference using System.Runtime.InteropServices.ComTypes;
add a JsonResult Method
public JsonResult ReadTextFile(string fileName)
{
string retString = string.Empty;
string path = Path.Combine(Server.MapPath("~/uploads") , fileName );
if (System.IO.File.Exists(path))
{
if (Path.GetExtension(path) == "doc" || Path.GetExtension(path) == ".docx")
{
Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
object miss = System.Reflection.Missing.Value;
object readOnly = true;
object wordPath = path;
Microsoft.Office.Interop.Word.Document docs = word.Documents.Open(
ref wordPath,
ref miss,
ref readOnly,
ref miss, ref miss, ref miss,
ref miss, ref miss, ref miss,
ref miss, ref miss, ref miss,
ref miss, ref miss, ref miss, ref miss);
for (int i = 0; i < docs.Paragraphs.Count; i++)
{
retString += " \r\n " + docs.Paragraphs[i + 1].Range.Text.ToString();
}
}
else if (Path.GetExtension(path) == "txt")
{
using (StreamReader sr = new StreamReader(path))
{
retString = sr.ReadToEnd();
}
}
}
return Json(retString, JsonRequestBehavior.AllowGet);
}
Note: I have considered to read only files with extension .doc, .docx and .txt any other extensions should be handled further

Related

How to convert byte to file asp.net MVC

I want to download the file that I uploaded in the database. The file stored in the byte array. I have created the getDataStudent function and it is working well.
My controller is below.
public class Student: Controller
{
private StudentViewModel getDataStudent(StudentViewModel model)
{
var students = db.students.ToList();
var documents = documentRepo.GetList_Documents();
var queryJoin1 =
from student in students
from document in documents.Where(w => student .UniqueNumber == w.UniqueNumber).DefaultIfEmpty()
select new StudentDto
{
ID = student.ID,
Name = student.Name,
File = document?.DetailFile ?? null, //file to download
};
IEnumerable <StudentDto> studentss= null;
studentss = queryJoin1;
return studentss;
}
public ActionResult Index(StudentViewModel model)
{
studentViewModel = getDataStudent(model);
return View(studentViewModel );
}
[HttpPost]
public FileResult DownloadFile()
{
//code
}
}
and my view is below
#model Student.Data.ViewModels.StudentViewModel
#using (Html.BeginForm())
{
<table class="table">
<tr>
<th>Name</th>
<th>File</th>
</tr>
#foreach (Student.Data.ViewModels.StudentViewModel item in Model)
{
<tr>
<td>#Html.DisplayFor(modelitem => item.Name)</td>
<td> #Html.DisplayFor(modelitem => item.File)</td>
</tr>
}
</table>
}
File Result is still empty, I confused using FileResult.
can you guys tell me how to download files using FileResult on the controller, using the getDataStudent function that I created.
I have never made a file download function before. please help:)
You can implement like this:
public FileStreamResult DownloadFile()
{
// get your students here
var students = ...
string name = "yourname.txt";
FileInfo info = new FileInfo(name);
if (!info.Exists)
{
using (StreamWriter writer = info.CreateText())
{
foreach(var item in students){
writer.WriteLine("{0} {1}", item.ID, item.Name);
}
}
}
return File(info.OpenRead(), "text/plain");
}

How do I change a partial view with a radio button click in .Net MVC and have some of the model state passed along to the partial view?

I'm trying to display a partial view in a div block named 'productButtonForm' based on a radio button click. The partial view appears to be called, but the passed model has null member variables. Can someone help me figure out where I've gone wrong? Below is what I've got:
Model
public class RetrieveAllModel
{
public Guid ConversationId { get; set; }
public List<RetrieveProductsModel> Products { get; set; }
public RetrieveOffersModel Offers { get; set; }
public int ProductType { get; set; }
}
View
#{
ViewBag.Title = "Easy Order";
int productCount = 0;
}
<legend>Offers/Products</legend>
#using (Html.BeginForm("ShowProductItems", "BrowseShopping"))
{
foreach (var type in Model.Products)
{
if (productCount > 0 && productCount % 5 == 0)
{
<br/>//break after every 5 products
}
#type.Name
#Html.RadioButtonFor(model => model.ProductType, type.ID, Model);
<label> </label>
productCount = productCount + 1;
}
<div class="col-lg-5 col-md-6 col-sm-12" id="productButtonForm">
</div>
}
Controller
public PartialViewResult ShowProductItems()
{
return PartialView("RetrieveProducts", new RetrieveAllModel() {Products = new List<RetrieveProductsModel>()});
}
[HttpPost]
public PartialViewResult ShowProductItems(RetrieveAllModel model)
{
//The passed model only has the ProductType set, every other
//member variable is null
return PartialView("RetrieveProducts", model);
}
Script file
$(function() {
$("[name=ProductType]").on('change',
function() {
var $radio = $(this);
var myurl = "ShowProductItems?ProductType=" + $radio.val();
console.log("We hit the script");
$.ajax({
url: myurl,
type: 'POST',
success: function(data) {
$("#productButtonForm").append(data);
}
});
});
});
I had a few issues going. Aside from what Stephen mentioned above, I had two data models that needed to be represented in the same button group. To address that, I had to use Html.RadioButton instead of RadionButtonFor. Also, I needed to access the controller's established conversation with the client to access the model state of the current view. Once I got those in place, the partial view changes as desired. Below are the changes I made to fix my triggering problem.
Model
public class RetrieveAllModel
{
public Guid ConversationId { get; set; }
public List<RetrieveProductsModel> Products { get; set; }
public RetrieveOffersModel Offers { get; set; }
public string ProductType { get; set; }
}
public class RetrieveCatalogModel
{
public List<BrowseDataItemModel> AvailableBrowseItems { get; set; }
}
public class RetrieveOffersModel : RetrieveCatalogModel
{
public List<int> SelectedServiceIds { get; set; }
}
public class RetrieveProductsModel : RetrieveCatalogModel
{
public int ID { get; set; }
public string Name { get; set; }
public int Count { get; set; }
}
View
#model OrderServiceClient.Models.RetrieveAllModel
#{
ViewBag.Title = "Easy Order";
int productCount = 1;
string offers = "Offers";
}
#using (Html.BeginForm("ShowCatalog", "BrowseShopping"))
{
//since offers are not part of the dynamic product list, they need to be specifically identified
#offers<label> </label>
#Html.RadioButton("catalogName", "Offers", true, new { catalogName = "Offers", conversationid = Model.ConversationId })
<label> </label>
foreach (var type in Model.Products)
{
if (productCount > 0 && productCount % 5 == 0)
{
<br/>//break after every 5 products
}
#type.Name<label> </label>
#Html.RadioButton("catalogName", type.Name, new { catalogName = type.Name, conversationid = Model.ConversationId })
<label> </label>
productCount = productCount + 1;
}
}
...
<div class="row">
#{Html.RenderPartial("RetrieveCatalogs", Model.Offers.AvailableBrowseItems);}
</div>
Partial View
#model List<OrderServiceClient.Models.BrowseDataItemModel>
#if (Model != null)
{
<div class="col-lg-7 col-md-6 col-sm-12 offers-container" id="shoppingcatalog">
<table class="table table-striped">
<tr>
<th>Data Type</th>
<th>Name</th>
<th>Price</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr class="offerList">
<td>#item.DataType</td>
<td>#item.Name</td>
<td>#string.Format($"{item.Amount,0:C2}")</td>
<td><a class="addService" dataType="#item.DataType" serviceId="#item.ServiceId" serviceName="#item.Name" amount="#item.Amount">Add</a></td>
</tr>
}
</table>
</div>
}
Controller
public PartialViewResult ShowCatalog()
{
RetrieveCatalogModel rcm = new RetrieveCatalogModel();
rcm.AvailableBrowseItems = new List<BrowseDataItemModel>();
return PartialView("RetrieveCatalogs", rcm.AvailableBrowseItems);
}
[HttpPost]
public PartialViewResult ShowCatalog(string catalogName, Guid conversationid)
{
if (catalogName.Equals("Offers"))
{
RetrieveOffersModel offers = new RetrieveOffersModel();
var response = BrowseShoppingHelper.RetrieveOffers(conversationid, _client);
offers.AvailableBrowseItems = BuildOffersBrowseDataItemsModel(response).ToList();
return PartialView("RetrieveCatalogs", offers.AvailableBrowseItems);
}
else
{
var prodctFolderResponse = BrowseShoppingHelper.RetrieveProductFolders(conversationid, _client);
var output = (RetrieveProductFoldersCommandOutput) prodctFolderResponse.Body.Output;
RetrieveProductsModel rpm = new RetrieveProductsModel{Name = catalogName, AvailableBrowseItems = new List<BrowseDataItemModel>()};
foreach (var folder in output.Folders)
{
if (!catalogName.Equals(folder.Name)) continue;
var items = BuildProductBrowseItemsModel(
(RetrieveProductsInGroupCommandOutput) BrowseShoppingHelper
.RetrieveProductItems(conversationid, _client, folder).Body.Output);
rpm.AvailableBrowseItems.AddRange(items);
break;
}
return PartialView("RetrieveCatalogs", rpm.AvailableBrowseItems);
}
}
Script file
$(function() {
$("[name=catalogName]").on('change',
function () {
var $radio = $(this);
var myurl = "ShowCatalog?catalogName=" + $radio.val() + "&conversationid=" + $(this).attr('conversationid');
console.log("Catalog item is: " + $radio.val() + " and id is: " + $(this).attr('conversationid'));
$.ajax({
url: myurl,
type: 'POST',
success: function (data) {
$("#shoppingcatalog").html(data);
}
});
});
});

MVC 4 Asp.net ,using File Upload code How to save images in Database

here is my view
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table>
<tr>
<td>File :</td>
<td><input type="file" name="File" id="file" /> </td>
</tr>
<tr>
<td><input type="submit" name="submit" value="upload" /></td>
</tr>
Here is my Controller
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Picture picture)
{
if (picture.File.ContentLength > 0)
{
var fileName = Path.GetFileName(picture.File.FileName);
var path = Path.Combine(Server.MapPath("~/Content/Images"), fileName);
picture.File.SaveAs(path);
}
return RedirectToAction("Index");
}
and Model:
namespace FileUpload.Models
{
public class Picture
{
public HttpPostedFileBase File { get; set; }
}
This code helps me to save image in my MVC project root Image folder , but I want to save it to my database . I have tried many tutorial but could not succeed yet ... '
I am Actually making the student form every student will register his picture.
Convert your image into bytes and then store it in your database
[HttpPost]
public ActionResult Index(Picture picture)
{
byte[] Image;
if (Request.Files["files"] != null)
{
using (var binaryReader = new BinaryReader(Request.Files["file"].InputStream))
{
Image = binaryReader.ReadBytes(Request.Files["files"].ContentLength);
}
Picture.File =Image;
}
return RedirectToAction("Index");
}
Model
public class Picture
{
public byte[] File { get; set; }
}
View For Displaying Image
if (Model.File != null)
{
string imageBase64 = Convert.ToBase64String(Model.File );
string imageSrc = string.Format("data:image/gif;base64,{0}", imageBase64);
<img src="#imageSrc" width="100" height="100" />
}

Persist ID throughout ASP.NET MVC Views

Basically I have an Image Upload controller, that I am inserting in pages as follows :-
<div id='imageList'>
<h2>Upload Image(s)</h2>
#{
if (Model != null)
{
Html.RenderPartial("~/Views/File/ImageUpload.cshtml", new MvcCommons.ViewModels.ImageModel(Model.Project.ProjectID));
}
else
{
Html.RenderPartial("~/Views/File/ImageUpload.cshtml", new MvcCommons.ViewModels.ImageModel(0));
}
}
</div>
So I am passing an ID to the ImageUpload, in this case the ProjectID, so that I can include it in my insert.
Now this is piece of code is populating an ImageModel(id), in my case its ProjectID :-
public ImageModel(int projectId)
{
if (projectId > 0)
{
ProjectID = projectId;
var imageList = unitOfWork.ImageRepository.Get(d => d.ItemID == projectId && d.PageID == 2);
this.AddRange(imageList);
}
}
and this in turn leads to the ImageUploadView.cshtml :-
<table>
#if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td>
<img src= "#Url.Content("/Uploads/" + item.FileName)" />
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
</tr>
}
}
</table>
#using (Html.BeginForm("Save", "File", new { ProjectID = Model.ProjectID },
FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type="submit" value="submit" /> <br />
<input type="text" name="description" />
}
So far so good, however my problem is that the first time
new { ProjectID = Model.ProjectID }
is correctly populated with the ProjectID, however, when I upload an image, the ProjectID is lost, and becomes zero. Is there a way I can persist the ProjectID for the second time?
Thansk for your help and time.
********* UPDATE *************************
After the upload, the Action is as follows inside the FileController :-
public ActionResult Save(int ProjectID)
{
foreach (string name in Request.Files)
{
var file = Request.Files[name];
string fileName = System.IO.Path.GetFileName(file.FileName);
Image image = new Image(fileName, Request["description"]);
ImageModel model = new ImageModel();
model.Populate();
model.Add(image, file);
}
return RedirectToAction("ImageUpload");
}
You can pass the projectId as a route value from the RedirectToAction. You should change the ImageUpload action to accept the projectId.
public ActionResult Save(int projectId)
{
....
return RedirectToAction("ImageUpload", new { projectId = projectId });
}
public ActionResult ImageUpload(int projectId)
{
var model = .. get the model from db based on projectId
return View("view name", model);
}

File Uploading in Asp.Net MVC

I am trying to make a file uploading page in my MVC project. First of all i want to manage this locally.
My Questions are:
1- Here is my controller and view. Is there any thing that I have to do to make this code work? I mean defining a model or using jquery, etc. What is the process when a file is being uploaded?
[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase uploadFile)
{
if (uploadFile.ContentLength > 0)
{
string filePath = Path.Combine(HttpContext.Server.MapPath("C:/Users/marti/../PhotoGallery/myimages"),
Path.GetFileName(uploadFile.FileName));
uploadFile.SaveAs(filePath);
}
return View();
}
Here is the View:
<input name="uploadFile" type="file" />
<input type="submit" value="Upload File" />
2- When i debug this, It never goes to controller.
You may need the enctype='multipart/form-data' on your view form:
#model ImageModel
#{
ViewBag.Title = "New Image";
}
<div class="content-form-container width-half">
<form id='PropertiesForm' action='#Url.Action(ImageController.Actions.Add, ImageController.Name)' method='post' enctype='multipart/form-data' class='content-form'>
#Html.Partial("ImageName")
<fieldset class='content-form-1field'>
<div class='legend'>
file to upload
</div>
#Html.LabelledFileInput(ImageView.FileName, string.Empty)
</fieldset>
<div class='buttons'>
#Html.Button("button-submit", "submit")
</div>
</form>
</div>
#section script{
#Html.JavascriptInclude("~/js/image/new.min.js")
}
And here is my controller code:
[HttpPost]
[MemberAccess]
public ActionResult Add()
{
var name = ImageView.ImageName.MapFrom(Request.Form);
if (Request.Files.Count == 0)
{
RegisterFailureMessage("No file has been selected for upload.");
return ValidationFailureAdd(name);
}
var file = Request.Files[0];
if (file == null || file.ContentLength == 0)
{
RegisterFailureMessage("No file has been selected for upload or the file is empty.");
return ValidationFailureAdd(name);
}
var format = ImageService.ImageFormat(file.InputStream);
if (format != ImageFormat.Gif && format != ImageFormat.Jpeg && format != ImageFormat.Png)
{
RegisterFailureMessage("Only gif, jpg and png files are supported.");
return ValidationFailureAdd(name);
}
if (query.HasName(name))
{
RegisterFailureMessage(string.Format("Image with name '{0}' already exists.", name));
return ValidationFailureAdd(name);
}
using (var scope = new TransactionScope())
{
var id = Guid.NewGuid();
var fileExtension = ImageService.FileExtension(format);
Bus.Send(new AddWikiImageCommand
{
Id = id,
Name = name,
FileExtension = fileExtension
});
var path = Path.Combine(ApplicationConfiguration.MediaFolder,
string.Format("{0}.{1}", id.ToString("n"), fileExtension));
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
file.SaveAs(path);
scope.Complete();
}
return RedirectToAction(Actions.Manage);
}
There are some custom bits in there so you can ignore those. The gyst of what you need should be there.
HTH

Resources