I uploaded multiple files as bytes into database table and how to download files as zip now? My code as below:
View:
#using (Html.BeginForm(Html.BeginForm("upload", "Home", FormMethod.Post, new { #id = "form", enctype = "multipart/form-data" })))
{
<input type="file" multiple="multiple" name="files" id="files" />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Submit" class="btn btn-default" />
</div>
</div>
}
controller:
public FileContentResult GetFile(int id)
{
SqlDataReader rdr; byte[] fileContent = null;
string mimeType = ""; string fileName = "";
string constr = WebConfigurationManager.ConnectionStrings["DbContextModel"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
var qry = "SELECT * FROM myTable WHERE ID = #ID";
var cmd = new SqlCommand(qry, con);
cmd.Parameters.AddWithValue("#ID", id);
con.Open();
rdr = cmd.ExecuteReader();
if (rdr.HasRows)
{
rdr.Read();
fileContent = (byte[])rdr["Attachments"];
}
}
return File(fileContent, "application/zip", "download.zip");
}
Model:
public partial class myTable
{
public int id {get;set;}
public byte[] Attachments { get; set; }
}
The download.zip file cannot be opened. "The compressed zipped folder is invalid". Please advise. Thanks in advance.
upload function:
...
byte[] bytes = new byte[] { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
MemoryStream target = new MemoryStream();
foreach (var file in files)
{
if (file.ContentLength > 0)
{
file.InputStream.CopyTo(target);
bytes = target.ToArray();
}
}
Appending the data for each uploaded file into a single stream doesn't create a valid zip file. You need to generate a valid zip file to store in the database.
For example:
byte[] bytes;
var target = new MemoryStream();
using (var zip = new ZipArchive(target, ZipArchiveMode.Create, true))
{
foreach (var file in files)
{
string name = Path.GetFileName(file.FileName);
ZipArchiveEntry entry = zip.CreateEntry(name);
using (Stream entryStream = entry.Open())
{
file.InputStream.CopyTo(entryStream);
}
}
bytes = target.ToArray();
}
ZipArchive Class
Related
I am able to Upload a Single Text File when I am trying to upload multiple Files its only taking Single
File can some one help me how to upload multiple text file:
public DemoController(IConfiguration configuration)
{
_configuration = configuration;
}
My Create Method:
public async Task<IActionResult> Create(IFormFile files)
{
string blobstorageconnection = _configuration.GetValue<string>("blobstorage");
byte[] dataFiles;
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("demodata");
BlobContainerPermissions permissions = new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
};
string systemFileName = files.FileName;
await cloudBlobContainer.SetPermissionsAsync(permissions);
await using (var target = new MemoryStream())
{
files.CopyTo(target);
dataFiles = target.ToArray();
Console.WriteLine("upload files Successfully");
}
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(systemFileName);
await cloudBlockBlob.UploadFromByteArrayAsync(dataFiles, 0, dataFiles.Length);
return View();
}
My View:(Create.cs html)
#{
ViewData["Title"] = "Create";
}
<div class="row">
<div class="col-md-6">
<form method="post" enctype="multipart/form-data" asp-controller="Demo" asp-action="Create">
<div class="form-group">
<label> Select File </label>
<input class="form-control" name="files" multiple="multiple" type="file" />
</div>
<div class="form-group">
<input class="btn btn-success" type="submit" value="Submit" id="demo" text="Succcessfully Uploaded" />
</div>
</form>
</div>
Please try something like the following (untested code):
public async Task<IActionResult> Create(List<IFormFile> files)
{
string blobstorageconnection = _configuration.GetValue<string>("blobstorage");
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("demodata");
BlobContainerPermissions permissions = new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
};
await cloudBlobContainer.SetPermissionsAsync(permissions);
foreach (var formFile in files)
{
byte[] data;
string systemFileName = formFile.FileName;
await using (var target = new MemoryStream())
{
formFile.CopyTo(target);
data = target.ToArray();
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(systemFileName);
await cloudBlockBlob.UploadFromByteArrayAsync(data, 0, data.Length);
}
}
return View();
}
Essentially the idea is to pass the collection of files and then loop over this collection in your controller action and upload each item individually.
File content result in mvc , no errors but file not downloading , can anyone find the issue pls...
public FileContentResult download(string data)
{
StringBuilder MyStringBuilder = new StringBuilder();
DataTable tblTemp = new DataTable();
MyStringBuilder.Append("select up.file_upload_pk,up.filename,up.contenttype,up.bytes from xxx up where up.yyy='xx'");
SAPDashboard.dl.clsDb objDB = new SAPDashboard.dl.clsDb(dl.clsDb.connection.Dashboard);
tblTemp = objDB.getTable(MyStringBuilder.ToString());
byte[] bytes=null;
string fileName= string.Empty;
string contentType=string.Empty;
string datas = tblTemp.Rows[0]["bytes"].ToString();
bytes = Encoding.ASCII.GetBytes(datas);
byte[] byteArray = bytes;
contentType = Convert.ToString(tblTemp.Rows[0]["contenttype"] == DBNull.Value ? "" : tblTemp.Rows[i]["contenttype"]);
fileName = Convert.ToString(tblTemp.Rows[0]["filename"] == DBNull.Value ? "" : tblTemp.Rows[i]["filename"]);
return File(bytes, contentType,fileName);
}
output parameter value
bytes= {byte[117808]},
contentType= "application/pdf",
fileName= "PaySlip636269030754635548.pdf"
I achieved FileDownloads by implementing something similar to the simplified following code, hope it helps.
View
#model List<string>
<h2>Downloads</h2>
<table>
<tr>
<th>File Name</th>
<th>Link</th>
</tr>
#for (var i = 0; i <= Model.Count-1; i++)
{
<tr>
<td>#Model[i].ToString() </td>
<td>#Html.ActionLink("Download",
"Download", new { ImageName = #Model[i].ToString() }) </td>
</tr>
}
</table>
Controller
public ActionResult Downloads()
{
var dir = new System.IO.DirectoryInfo(Server.MapPath("~/App_Data/uploads/"));
System.IO.FileInfo[] fileNames = dir.GetFiles("*.*"); List<string> items = new List<string>();
foreach (var file in fileNames)
{
items.Add(file.Name);
}
return View(items);
}
public FileResult Download(string ImageName)
{
var FileVirtualPath = "~/App_Data/uploads/" + ImageName;
return File(FileVirtualPath, "application/force-download", Path.GetFileName(FileVirtualPath));
}
I want to upload Images to a database. The database contains url images and images uploads to folder in file system. I have the following tables in the database,
Furniture
MainFileDetails (1-1 relationship with Furniture) where store the main image
FileDetails (1-Many relationship with Furniture) where we store other images associated with Furniture.
Here is my code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Furniture furniture , HttpPostedFileBase fileTwo, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
for (int i = 0; i < Request.Files.Count; i++)
{
fileTwo = Request.Files[i];
if (fileTwo != null && fileTwo.ContentLength > 0)
{
var fileNameTwo = Path.GetFileName(fileTwo.FileName);
MainFileDetails mainFileDetail = new MainFileDetails()
{
FileName = fileNameTwo,
Extension = Path.GetExtension(fileNameTwo),
Id = Guid.NewGuid(),
FurnitureId = furniture.FurnitureId
};
var pathMain = Path.Combine(Server.MapPath("~/Upload/MainPage/"), mainFileDetail.Id + mainFileDetail.Extension);
fileTwo.SaveAs(pathMain);
db.Entry(mainFileDetail).State = EntityState.Modified;
db.SaveChanges();
FileDetail fileDetail = new FileDetail()
{
NameFile = fileNameTwo, //or mainFileDetail.FileName
Extension = Path.GetExtension(fileNameTwo), //or mainFileDetail.Extension
Id = Guid.NewGuid(),
FurnitureId = furniture.FurnitureId //or mainFileDetail. FurnitureId
};
var path = Path.Combine(Server.MapPath("~/Upload/"), fileDetail.Id + fileDetail.Extension);
file.SaveAs(path);
db.Entry(fileDetail).State = EntityState.Added;
}
}
db.Entry(furniture).State = EntityState.Modified;
db.SaveChanges();
TempData["message"] = string.Format("Changes in \"{0}\" has been saved", furniture.Name);
return RedirectToAction("Index");
}
ViewBag.CategoryId = new SelectList(db.Categories, "CategoryId", "Name", furniture.CategoryId);
return View(furniture);
}
My View:
#model FurnitureStore.Entities.Furniture
....
#using (Html.BeginForm("Edit", "Furnitures", FormMethod.Post, new { enctype = "multipart/form-data"}))
{
....
#Html.HiddenFor(model => model.FurnitureId)
#Html.LabelFor(model => model.Name)
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
.... // more inputs for properties of the model
#Html.LabelFor(model => model.CategoryId, "Category")
#Html.DropDownList("CategoryId", null)
#Html.ValidationMessageFor(model => model.CategoryId, "", new { #class =
// Main file
<input type="file" name="fileTwo" />
#if(Model.MainFileDetails.Id == null)
{
<div class="form-control-static">No image</div>
}
else
{
<img src="~/Upload/MainPage/#(Model.MainFileDetails.Id + Model.MainFileDetails.Extension)" width="240" height="240" />
}
// Other files
<input type="file" name="file" multiple="multiple" />
<ul class="attachment">
#foreach (var item in Model.FileDetails)
{
<li style="list-style-type:none; display:inline;">
<img src="~/Upload/#(item.Id + item.Extension)" />
X
</li>
}
</ul>
<input type="submit" value="Save" class="btn btn-primary" />
}
But I have a problem. All photo just uploads to the Upload/MainPage folder. I want to upload photo separately to MainPage in one table and separately to gallery (other table).
How can I fix my code, because last uploaded photo in gallery table replaces photo in MainPage?
The foreach loop in your controller method is looping through every file you have uploaded, and then you create a new MainFileDetails for each file and save it. You need to get the 'main file' from the first file input and save it to MainFileDetails and then loop through the files in the second file input and save each of them to FileDetails.
To solve the immediate problem, change your method to
public ActionResult Edit(Furniture furniture , HttpPostedFileBase fileTwo, IEnumerable<HttpPostedFileBase> file)
and those parameters will be bound with the values for the file inputs. Then its simply
if (ModelState.IsValid)
{
if (fileTwo != null && fileTwo.ContentLength > 0)
{
// create an instance of MainFileDetails and set its properties based on
// the values of fileTwo and save
}
foreach (HttpPostedFileBase image in file)
{
// create an instance of FileDetails and set its details based on
// the values of image and save
}
db.Entry(furniture).State = EntityState.Modified;
db.SaveChanges();
....
There are however numerous other potential issues with your code.
Rule 1. Your editing data, so always use a view model. What is
ViewModel in
MVC?
Its unclear why you need a separate 1 to 1 table for the main image.
The properties for that could be stored in the Furniture table.
Alteratively you could just have the 1 to Many table, and have a
bool IsMainImage property which would allow you to easily swap
which is the main image.
You images table (FurnitureImages would be a more appropriate name)
should include a auto-incremented int ID for the PK and properties
for the file path and file display name
If ModelState is invalid, you return the view, but all the files
are lost and the poor user needs to re-select them all again
Your view models should be
public class FurnitureVM
{
public int? ID { get; set; }
[Required( ... )]
public string Name { get; set; }
.... // other properties of Furniture that you need in the view
[Required( ... )]
public int? Category { get; set; }
public IEnumerable<SelectListItem> CategoryList { get; set; }
public HttpPostedFileBase MainFile { get; set; }
public IEnumerable<HttpPostedFileBase> SecondaryFiles { get; set; }
public ImageVM MainImage { get; set; }
public List<ImageVM> SecondaryImages { get; set; }
}
public class ImageVM
{
public int? ID { get; set; }
public string Path { get; set; }
public string DisplayName { get; set; }
}
And the view
#model yourAssembly.FurnitureVM
....
#using (Html.BeginForm("Edit", "Furnitures", FormMethod.Post, new { enctype = "multipart/form-data"}))
{
// Note: no need for a hidden input for the ID property assuming your using the default routing
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
.... // more inputs for properties of the model
#Html.LabelFor(m => m.Category)
#Html.DropDownListFor(m => m.Category, Model.CategoryList, "Please select")
#Html.ValidationMessageFor(m => m.Category)
// Main file
#Html.TextBoxFor(m => m.MainFile, new { type = "file" })
#Html.ValidationMessageFor(m => m.MainFile)
if (Model.MainImage != null)
{
#Html.HiddenFor(m => m.MainImage.ID)
#Html.HiddenFor(m => m.MainImage.Path)
#Html.HiddenFor(m => m.MainImage.DisplayName)
<img src="#MainImage.Path" alt="#MainImage.DisplayName" />
}
// Secondary files
#Html.TextBoxFor(m => m.SecondaryFiles, new { type = "file", multiple = "multiple" })
#Html.ValidationMessageFor(m => m.SecondaryFiles)
for (int i = 0; i < Model.SecondaryImages.Count; i++)
{
#Html.HiddenFor(m => m.SecondaryImages[i].ID)
...
}
<input type="submit" value="Save" />
}
And the controller POST method
public ActionResult Edit(FurnitureVM model)
{
// Save the files
if (model.MainFile != null && model.MainFile.ContentLength > 0)
{
string displayName = model.MainFile.FileName;
string extension = Path.GetExtension(displayName)
string fileName = string.Format("{0}{1}", Guid.NewGuid(), extension)
string path = Path.Combine("~/Images/", fileName);
model.MainFile.SaveAs(Server.MapPath(path));
model.MainImage = new ImageVM() { Path = path, DisplayName = displayName };
}
foreach (HttpPostedFileBase file in model.SecondaryFiles)
{
....
}
if (!ModelState.IsValid)
{
model.CategoryList = new SelectList(....); // repopulate the SelectList
return View(model);
}
// Get the data model from the database
Furniture furniture = db.Furniture.Where(x => x.FurnitureId == model.ID).FirstOrDefault()
// Update properties based on view model
furniture.Name = modell.Name;
...
// Update the main image
if (model.MainImage != null && !model.MainImage.ID.HasValue)
{
FurnitureImages image = new FurnitureImages()
{
image.Path = model.MainImage.Path;
image.DisplayName = model.MainImage.DisplayName;
image.IsMainImage = true;
furniture.Images.Add(image);
}
// Update secondary images
IEnumerable<ImageVM> newImages = model.SecondaryImages.Where(x => x.ID == null);
foreach (ImageVM image in newImages)
{
.... // add to the collection
}
// Save and redirect
}
I have one list where I need to export data in excel. The Code in View:
$("#btnExport").click(function () {
//Used for Export to excel
window.open('#Url.Action("ExportHotelUtilizationListToExcel","DutyTravel")');
});
<input type="button" value="Export to Excel" name="submitButton" id="btnExport" class="k-button" />
and below is my controller method
public FileResult ExportHotelUtilizationListToExcel()
{
var grid = new System.Web.UI.WebControls.GridView();
List<DutyTravelHotelUtilization> lstSeparation = null;
if (Session["HotelUtilizationDetails"] != null)
{
lstSeparation = (List<DutyTravelHotelUtilization>)HttpContext.Session["HotelUtilizationDetails"];
grid.DataSource = from d in lstSeparation
select new
{
RequestCode = d.DutyTravelReqId,
StffNumber = d.StaffNumber,
StaffName = d.StaffName,
CityCode = d.CityCode,
CityName = d.CityName,
HotelCategory = d.HotelCategory,
HotelName = d.HotelName,
CurrencyInQAR = d.QurrencyQAR,
CheckInDate = Convert.ToDateTime(d.CheckInDate).ToString("dd-MMM-yyyy"),
CheckOutDate = Convert.ToDateTime(d.CheckOutDate).ToString("dd-MMM-yyyy"),
Duration = d.Duration
};
}
grid.DataBind();
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
grid.RenderControl(htw);
return File(new System.Text.UTF8Encoding().GetBytes(sw.ToString()), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Contacts.xlsx");
}
It is showing download option and able to open in OpenOffice but in MS Office 2010 showing error message about some format issue.
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