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
Related
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)" />
I'm trying to save images and videos to a separate folder and not in the database, as from what I read it is best practice not to store there. I am able to take in the photo, then save the URL string to the database. Files are saving to the correct location.
After I pull up the view to display the image, it's not showing up. I can see it is a broken link. But not sure how to correct it.
The controller:
[HttpPost]
public IActionResult AddPost(AddPostViewModel addPost, IFormFile file)
{
//Setting the extra data need for the post
addPost.post.DateModified = DateTime.Now;
addPost.post.DatePosted = DateTime.Now;
//Saving the image to a location
SaveImage saveImage = new SaveImage();
Task<String> filePath = saveImage.UploadFile(file);
addPost.post.PostImageVideo = filePath.Result;
//Adding and saving the post to the database and then returning to the admin panel.
_context.Post.Add(addPost.post);
_context.SaveChanges();
ViewBag.SessionUserFirstName = HttpContext.Session.GetString("UserFirstName");
ViewBag.isAdmin = HttpContext.Session.GetString("IsAdmin");
return RedirectToAction("AdminPanel");
}
The medthod being called to save the image:
public async Task<String> UploadFile(IFormFile file)
{
var fileName = "";
var filePath = "";
//adding the filepath to the database and saving the path.
if (file != null && file.Length > 0)
{
fileName = Path.GetFileName(file.FileName);
filePath = Path.Combine(Directory.GetCurrentDirectory(),#"~/wwwroot/images/", fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
return filePath.ToString();
}
Then the view that pulls in the link from the entity or pulling from database
#{
ViewData["Title"] = "Post";
}
<div class="container">
<div class="row">
<div class="col-md-12 text-center">
<h1>#Model.post.Title</h1>
</div>
</div>
<div class="row">
<!--This is grabbing the link for the post.-->
<img src="#Model.post.PostImageVideo" />
<div class="col-md-12">
<p>#Model.post.Body</p>
</div>
</div>
</div>
It seems like when I look at the link, it isn't grabbing the wwwroot folder that it is located in, it just goes right into the images. Not sure how to correct it.
I think I have it:
When I called the saveImage method I was returning the filepath. I had it return the filename and put in and additional string in front to save to the database like so:
addPost.post.PostImageVideo = "/images/" + fileName.Result;
Whether that is the correct way or not, not sure, but it works.
You may use FileContentResult to return the image as file to view.
public class ImageController : Controller
{
private readonly IHostingEnvironment _appEnvironment;
public ImageController(IHostingEnvironment appEnvironment)
{
_appEnvironment = appEnvironment;
}
public IActionResult Index()
{
return View();
}
public FileContentResult ShowImage()
{
string fileName = Path.Combine(_appEnvironment.WebRootPath, "images\\avatar.png").Replace("\\", "/");
byte[] imageData = null;
FileInfo fileInfo = new FileInfo(fileName);
long imageFileLength = fileInfo.Length;
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
imageData = br.ReadBytes((int)imageFileLength);
return File(imageData, "image/png");
}
}
View..
<img src="#Url.Action("ShowImage", "Image", new { area = "" })" class="user-image" alt="User Image">
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++;
}
}
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 )));
I am trying to implement a simple file upload, but having some troubles. When I hard-code the path it works fine. But for some reason, when I try to use a file upload, the controller name is being appended to the path
Hard coded path (what I'm trying to get):
#"C:\Users\Scott\Documents\The Business\MasterSpinSite\MasterSpin\MasterSpin\LOADME.txt"
Path I am getting an exception with (notice the "appz" controller name):
C:\Users\Scott\Documents\The Business\MasterSpinSite\MasterSpin\MasterSpin\appz\LOADME.txt'
My Controller
public ActionResult Load(spinnerValidation theData, HttpPostedFileBase file)
{
if (file.ContentLength > 0)
{
string filePath = Request.MapPath(file.FileName);
string input = System.IO.File.ReadAllText(filePath);
string[] lines = Regex.Split(input, "#!#");
// ...... do stuff
}
My View
<form action="" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" value="LOAD ME!">
</form>
What could be causing this behavior ?
You can save yourself the effort of the streams:
string filename = Request.Files["file"].FileName;
string filePath = Path.Combine(Server.MapPath("~/YourUploadDirectory"), filename);
HttpPostedFileBase postedFile = Request.Files["file"] as HttpPostedFileBase;
postedFile.SaveAs(filePath);
string input = File.ReadAllText(filePath);
try this:
public ActionResult Load(spinnerValidation theData, HttpPostedFileBase file)
if (file.ContentLength > 0)
{
var filePath = System.IO.Path.GetFileName(file.FileName);
using (System.IO.StreamReader sr = new System.IO.StreamReader(filePath))
{
var input = sr.ReadToEnd();
var lines = Regex.Split(input, "#!#");
}
}
}
(bug) System.IO.Path.GetFileName(file.FileName) return the name of file
Edit
change System.IO.Path.GetFileName(file.FileName) for Server.MapPath(file.FileName)
public ActionResult Load(spinnerValidation theData, HttpPostedFileBase file)
if (file.ContentLength > 0)
{
var filePath = Server.MapPath(file.FileName);
using (System.IO.StreamReader sr = new System.IO.StreamReader(filePath))
{
var input = sr.ReadToEnd();
var lines = Regex.Split(input, "#!#");
}
}
}
Edit II
or copy to diferent path:
public ActionResult Load(spinnerValidation theData, HttpPostedFileBase file)
if (file.ContentLength > 0)
{
var fileName = System.IO.Path.GetFileName(file.FileName);
var fileUpload = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(fileUpload);
if (System.IO.File.Exists(fileUpload))
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(fileUpload))
{
var input = sr.ReadToEnd();
var lines = Regex.Split(input, "#!#");
}
}
}
}