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">
Related
i have created method that create a User which in following i want it to create user Profile with it.
here is my code:
public Task CreateUser(User user, IFormFile image)
{
if (image is not null && image.Length > 0)
{
string uploads = Path.Combine(#"./", "Uploads");
Directory.CreateDirectory(uploads);
if (image.Length > 0)
{
var filename = Guid.NewGuid().ToString() + image.FileName;
string filePath = Path.Combine(uploads, filename);
using (Stream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
image.CopyTo(fileStream);
}
user.Image = filename;
}
}
else
{
user.Image = "";
}
return _user.InsertOneAsync(user);
}
but then when i want to create user in UI
#inject IUserData Userdata
await Userdata.CreateUser(user);
i got an error under createuser and it says i should pass the image parameter which when i pass it again gives me another error
can you please help me with saving this image?
thanks
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
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++;
}
}
"ilan" is a table in my database, ilan has a column named "kapak_foto".
Here is my code:
[HttpPost]
[ValidateInput(false)]
public ActionResult ilanver(ilan ilan,HttpPostedFileBase kapak_foto)
{
if (kapak_foto != null)
{
string kapakname = Path.GetFileNameWithoutExtension(kapak_foto.FileName)
+ "-" + Guid.NewGuid() + Path.GetExtension(kapak_foto.FileName);
Image orjres = Image.FromStream(kapak_foto.InputStream);
orjres.Save(Server.MapPath("~/Content/images/pics" + kapakname));
ilan dbres = new ilan();
dbres.kapak_foto = "/Content/images/pics" + kapakname;
}
The html part:
#using (Html.BeginForm("ilanver", "ilanver", FormMethod.Post, new { enctype="multipart/form-data" }))
{ <input type="file" name="kapak_foto"/>}
Firstly; the code is
orjres.Save(Server.MapPath("~/Content/images/pics/" + kapakname));
Second; if you will use the path of saved file, you must take the file location into antoher variable before to save;
var filePath = "/Content/images/pics/" + kapakname;
orjres.Save(Server.MapPath(filePath));
ilan dbres = new ilan();
dbres.kapak_foto = filePath;
// ... the other codes...
db.ilan.add(dbres); // if your databse name defined before as db!
db.SaveChanges();
If the filePath is correct for to save file, it can be usable for url.
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, "#!#");
}
}
}
}