DownloadFile in ASP mvc 4 from physical path - c#

I need to make downloading files from the server . Server is specified physical path.
the file is downloaded , but there are problems that I do not know how to fix .
1) All the files are named as "Download".2) does not have an extension . Help me, please, I'm new to ASP MVC
Code of Controller :
public ActionResult NIRInfo()
{
List<string> filesList = new List<string>();
var dir = new System.IO.DirectoryInfo(#"Z:\Docs");
System.IO.FileInfo[] fileNames = dir.GetFiles("*.*");
var xow = from i in db.NIRs where i.Id == id select i.File;
foreach (var i in xow)
{
fileNames = dir.GetFiles(i);
foreach (var f in fileNames)
{
filesList.Add(f.Name);
}
ViewData["fList"] = filesList;
}
return View(nir);
}
public FileResult Download(string Name)
{
return File(#"Z:\Docs\" + Name, MediaTypeNames.Application.Octet);
}
Code of view
#{ var fList = ViewData["fList"] as List<string>;}
#if (ViewData["fList"] != null)
{
<table>
#foreach (var f in fList)
{
<tr>
<td>
#f
</td>
</tr>
}
</table>
}

You need to specify a filename in method overload. Look at third parameter in File method
public FileResult Download(string Name)
{
return File(#"Z:\Docs\" + Name, MediaTypeNames.Application.Octet, "document.txt");
}

HttpResponseBase response;
response.Clear();
response.AddHeader("content-disposition", "attachment;filename=\"" + fileName + "\"");
response.TransmitFile(Path.Combine(FileName, Path.GetFileName(fileName )));

Related

How to display image from database filepath in asp.net core razor

as the title states. I have a dedicated directory in the wwwroot directory. the backend initially stores the whole path from the C: Drive then i changed it to the root directory. Am I suppose to store the path according to the solution explorer directory? If I use the full path i.e. from C: Drive or the path from wwwroot in solution explorer i get the same error.
Upload Logic
public async Task<IActionResult> OnPostAsync(IFormFile file)
{
if (!ModelState.IsValid)
{
return Page();
}
var UserDb = await _context.User.FindAsync(User.ID);
string folderName = "wwwroot/Uploads/Profile/" + UserDb.ID;
string webRootPath = _hostEnvironment.ContentRootPath;
string newPath = Path.Combine(webRootPath, folderName);
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
string fileName = UserDb.ID + ".jpg";
string fullPath = Path.Combine(newPath, fileName);
Console.WriteLine(fullPath);
string envpath = folderName + "/" + fileName;
using (var stream = new FileStream(fullPath, FileMode.Create))
{
file.CopyTo(stream);
stream.Flush();
}
UserDb.ImageUrl = folderName;
_context.Attach(UserDb).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!UserExists(User.ID))
{
return NotFound();
}
else
{
throw;
}
}
var currentID = UserDb.ID;
return RedirectToPage("Socials", new { id = currentID });
}
private bool UserExists(int id)
{
return _context.User.Any(e => e.ID == id);
}
}
Trying to Display The Image
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.User.ImageUrl)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.User.ImageUrl)
<img src="#Url.Content(#Model.User.ImageUrl)" />
</dd>
Solution Explorer
Your #Model.User.ImageUrl should equal to /Uploads/Profile/1018/1018.jpg. Be sure add single slash at the beginning and specific the file name.
So maybe you need change your backend code like below:
string folderName = "Uploads/Profile/" + UserDb.ID; //"Uploads/Profile/2017"
//change here...
string webRootPath = _hostEnvironment.WebRootPath; //"C:\\YourSolutionLocation\\wwwroot"
string newPath = Path.Combine(webRootPath, folderName);//"C:\\YourSolutionLocation\\wwwroot\\Uploads/Profile/2017"
//....
string envpath = folderName + "/" + fileName; //"Uploads/Profile/2017/2017.jpg"
//....
UserDb.ImageUrl = envpath;
Then change the razor pages like below:
<img src="/#Url.Content(#Model.User.ImageUrl)" />

Image is not display in index page

I have a problem with the index page. On this index page, we can see the uploaded Ad details like Ad title, description, and link except for the uploaded image. When I inspect i can see
<img src="/images/Ad/ad2.png" width="50px" height="50px">
On the index page, i use this code
<td>
<img src="#Url.Content(String.Format("/images/Ad/{0}",item.ImagePath))" width="50px" height="50px" />
</td>
This is my Controller
public IActionResult Create([Bind("AdID,Title,ImagePath,Description,Link")] AdTbl adTbl, List<IFormFile> FormFile)
{
if (FormFile != null && FormFile.Count > 0)
{
string folderName = "images/Ad";
string webRootPath = _hostingEnvironment.WebRootPath;
string newPath = Path.Combine(webRootPath, folderName);
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
foreach (IFormFile item in FormFile)
{
if (item.Length > 0)
{
string fileName = ContentDispositionHeaderValue.Parse(item.ContentDisposition).FileName.Trim('"');
string fullPath = Path.Combine(newPath, fileName);
adTbl.AdID = Guid.NewGuid();
adTbl.ImagePath = fileName;
using (var stream = new FileStream(fullPath, FileMode.Create))
{
item.CopyTo(stream);
}
_adTblRepository.CreateAd(adTbl);
}
}
_notyf.Success("Advertisement added successfully");
return RedirectToAction(nameof(Index));
}
return View(adTbl);
}
**The main thing is that the same code is using on different pages and that's worked. And I noticed that one thing when we change the location this problem occurs again

ienumerable , looping in mvc

I'm creating a page with multiple file uploader in MVC.
What I want to achieve is when I submit values the images uploaded should be named as guid and an incrementing i value, like guid0 , guid1, guid2. I tried for loop but its saving only one image until loop ends . i++ isn't working though.
My controller looks like this:
public ActionResult Home(SomeClass someclass, IEnumerable<HttpPostedFileBase> files)
{
var guid = Guid.NewGuid().ToString();
someclass.filename = guid;
int i = 0;
foreach (var file in files)
{
if (file.ContentLength > 0)
{
var fileName = guid + "" + i + ".jpg";
var path = Path.Combine(Server.MapPath("~/Content/admin/Upload"), fileName);
file.SaveAs(path);
i++;
}
}
db.someclasses.Add(someclass);
db.SaveChanges();
return RedirectToAction("Preview");
}
And my view looks like this
<input type="file" name="files" id=1>
<input type="file" name="files" id=2>
Update : I'm receiving 11 files at the if loop but once they go through the loop there is only single image in the images folder named fdea36c3-545a-4e08-8af4-7fa6bd88bc6b0 . what i'm trying to achieve is all 11 images named as fdea36c3-545a-4e08-8af4-7fa6bd88bc6b0, fdea36c3-545a-4e08-8af4-7fa6bd88bc6b1,fdea36c3-545a-4e08-8af4-7fa6bd88bc6b2.....so on .
Well, I am not very familiar with HTML inputs, but I think you should use "multiple" attribute in you SINGLE file input tag.
Or rename "files" to "files[]".
Look at this
try this way if you have multiple file controls on view.
you can even have Guid initialized for each file and can ignore appending i to the name.
public class MultipleFilesForm
{
public HttpPostedFileBase file1 {get;set;}
public HttpPostedFileBase file2 {get;set;}
}
action method as
public ActionResult Home(MultipleFilesForm form)
{
var guid = Guid.NewGuid().ToString();
someclass.filename = guid;
int i = 0;
if(form.file1 != null)
{
var file = form.file1;
if (file.ContentLength > 0)
{
var fileName = guid + i.ToString() + Path.GetExtension(file.FileName));
var path = Path.Combine(Server.MapPath("~/Content/admin/Upload"), fileName);
file.SaveAs(path);
i++;
}
}
if(form.file2 != null)
{
//handle file
}
...
}
[UPDATE]
try this way
try this as well.
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
if (file != null && file.ContentLength > 0)
{
var fileName = guid + i.ToString() + Path.GetExtension(file.FileName));
var path = Path.Combine(Server.MapPath("~/Content/admin/Upload"), fileName);
file.SaveAs(path);
i++;
}
}

Update model property in Asp.net mvc kendo ui async file upload

I have a kendo ui async file upload with the following options on my view.
<div class="demo-section">
#(Html.Kendo().Upload()
.Name("files")
.Async(a => a
.Save("Save", "Upload")
.AutoUpload(true)
)
)
</div>
In the corresponding action method ,I would like to set my model's properties for filename .Shown below is what i have currently .
public ActionResult Save(IEnumerable<HttpPostedFileBase> files)
{
// The Name of the Upload component is "files"
if (files != null)
{
foreach (var file in files)
{
// Some browsers send file names with full path.
// We are only interested in the file name.
var fileName = Path.GetFileName(file.FileName);
var physicalPath = Path.Combine(Server.MapPath("~/App_Data"), fileName);
// The files are not actually saved in this demo
// file.SaveAs(physicalPath);
}
}
// Return an empty string to signify success
return Content("");
}
If there is a way to do it ,please let me know ..
public ActionResult Save(IEnumerable<HttpPostedFileBase> files)
{
var savedFilePaths = new List<string>();
var applicationPath = System.Web.HttpContext.Current.Request.Url.Scheme + "://" + System.Web.HttpContext.Current.Request.Url.Authority + System.Web.HttpContext.Current.Request.ApplicationPath + "/Content/Images/Others/";
// The Name of the Upload component is "files"
if (files != null)
{
foreach (var file in files)
{
// Some browsers send file names with full path.
// We are only interested in the file name.
var fileName = Path.GetFileName(file.FileName);
if (fileName != null)
{
fileName = DateTime.Now.ToString("yyyyMMddmm-") + fileName;
var physicalPath = Path.Combine(Server.MapPath("~/Upload/Hotel"), fileName);
file.SaveAs(physicalPath);
savedFilePaths.Add(applicationPath + fileName);
}
}
}
// Return an empty string to signify success
return Content("");
}

How to upload multiple files in mvc 5 to server and store file's path with Entity Framework

I am trying to save a list of files to the file system and the path to EF. I haven't found a complete tutorial online so I've mashed up a couple of blog posts to scope out what I need. I can save 1 file but I can't save multiple files. I know why though. It is because the list gets reinitialized after every file. I've tried to move things in and out of scope and tried initializing variables in other ways. Can someone take a look at my controller and see what I can do to fix?
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Exclude = "Id")] Incident incident, IEnumerable<HttpPostedFileBase> upload)
{
if (ModelState.IsValid)
{
if (upload != null)
{
int MaxContentLength = 1024 * 1024 * 10; //10 MB
string[] AllowedFileExtensions = new string[] { ".jpg, ", ".gif", ".png", ".pdf", ".doc", "docx", "xls", "xls" };
foreach (var file in upload)
{
if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf(".", StringComparison.Ordinal)).ToLower()))
{
ModelState.AddModelError("Upload", "Document Type not allowed. Please add files of type: " + string.Join(", ", AllowedFileExtensions));
}
else if (file.ContentLength > MaxContentLength)
{
ModelState.AddModelError("Upload", "Your file is too large. Maximum size allowed is: " + MaxContentLength + " MB");
}
else
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
var photo = new FilePath
{
FileName = Path.GetFileName(file.FileName),
FileType = FileType.Document
};
incident.FilePaths = new List<FilePath> { photo };
}
}
ModelState.Clear();
}
db.Incidents.Add(incident);
db.SaveChanges();
return RedirectToAction("Index");
}
Initialize the list before loop:
incident.FilePaths = new List<FilePath>();
foreach(var file in upload)
{
// your code except last line
incident.FilePaths.Add(photo);
}
// rest of your code

Categories