'How do I upload pdf into a folder and store the path into a database, and be able to view the uploaded file? Thank you
Here is my controller code
namespace MyClassWorkApplication.Areas.Admin.Controllers
{
[Area("Admin")]
[Authorize(Roles = "Admin")]
public class ContentController : Controller
{
private readonly ApplicationDbContext _context;
private IWebHostEnvironment _env;
public ContentController(ApplicationDbContext context, IWebHostEnvironment env)
{
_context = context;
_env = env;
}
// GET: Admin/Content/Create
public IActionResult Create(int categoryItemId, int categoryId)
{
Content content = new Content
{
CategoryId = categoryId,
CatItemId = categoryItemId
};
return View(content);
}
// POST: Admin/Content/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,HTMLContent,VideoLink,CatItemId,CategoryId,PublicationPdfUrl")] Content content)
{
Profile profile = new Profile();
profile.Title = content.Title;
//loading remaining properties of the model from ViewModel
//uploading file....
string uniqueFileName = null;
if (content.PublicationPdfUrl != null)
{
string folder = "Publications/pdf/";
string serverFolder = Path.Combine(_env.WebRootPath, folder);
uniqueFileName = Guid.NewGuid().ToString() + "_" + content.PublicationPdfUrl.FileName;
string filePath = Path.Combine(serverFolder, uniqueFileName);
content.PublicationPdfUrl.CopyTo(new FileStream(filePath, FileMode.Create));
profile.PublicationPdfUrl = content.PublicationPdfUrl.FileName;
}
if (ModelState.IsValid)
{
content.CategoryItem = await _context.CategoryItem.FindAsync(content.CatItemId);
_context.Add(content);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index), "CategoryItem", new { categoryId = content.CategoryId });
}
return View(content);
}
// GET: Admin/Content/Edit/5
public async Task<IActionResult> Edit(int categoryItemId, int categoryId)
{
if (categoryItemId == 0)
{
return NotFound();
}
var content = await _context.Content.SingleOrDefaultAsync(item => item.CategoryItem.Id == categoryItemId);
content.CategoryId = categoryId;
if (content == null)
{
return NotFound();
}
return View(content);
}
// POST: Admin/Content/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,HTMLContent,VideoLink,CategoryId,PublicationPdfUrl")] Content content)
{
if (id != content.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(content);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ContentExists(content.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index), "CategoryItem", new { categoryId = content.CategoryId });
}
return View(content);
}
private bool ContentExists(int id)
{
return _context.Content.Any(e => e.Id == id);
}
}
}
My Second Controller
namespace MyClassWorkApplication.Controllers
{
public class ContentController : Controller
{
private readonly ApplicationDbContext _context;
public ContentController(ApplicationDbContext context)
{
_context = context;
}
public async Task<IActionResult> Index(int categoryItemId)
{
Content content = await (from item in _context.Content
where item.CategoryItem.Id == categoryItemId
select new Content
{
Title = item.Title,
VideoLink = item.VideoLink,
HTMLContent = item.HTMLContent,
PublicationPdfUrl = item.PublicationPdfUrl
}).FirstOrDefaultAsync();
return View(content);
}
}
}
This is my Model class (Content). It was reporting error with the IFormFile until I added the [NotMapped] attributes to it before the error disappears. However, It does not add the pdf Url into that database as I wanted.
public class Content
{
public int Id { get; set; }
[Required]
[StringLength(200, MinimumLength = 2)]
public string Title { get; set; }
[Display(Name = "HTML Content")]
public string HTMLContent { get; set; }
[Display(Name = "Video Link")]
public string VideoLink { get; set; }
public CategoryItem CategoryItem { get; set; }
[NotMapped]
public int CatItemId { get; set; }
//Note: This property cannot be
//named CategoryItemId because this would
//interfere with future migrations
//It has been named like this
//so as not to conflict with EF Core naming conventions
[NotMapped]
public int CategoryId { get; set; }
[NotMapped]
public IFormFile PublicationPdfUrl { get; set; }
}
public class Profile
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string HTMLContent { get; set; }
public string VideoLink { get; set; }
public CategoryItem CategoryItem { get; set; }
public int CatItemId { get; set; }
public int CategoryId { get; set; }
[Display(Name = "Upload your publication in pdf format")]
public string PublicationPdfUrl { get; set; }
}
}
This is my Create View
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Content</h4>
<hr />
<div class="row">
<div class="col-md-10">
<form method="post" enctype="multipart/form-data" asp-action="Create">
<input type="hidden" asp-for="CategoryId">
<input type="hidden" asp-for="CatItemId">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="HTMLContent" class="control-label"></label>
<textarea asp-for="HTMLContent" row="10" class="form-control"></textarea>
<span asp-validation-for="HTMLContent" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="VideoLink" class="control-label"></label>
<input asp-for="VideoLink" class="form-control" />
<span asp-validation-for="VideoLink" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PublicationPdfUrl" class="control-label"></label>
<div class="custom-file">
<input asp-for="PublicationPdfUrl" class="custom-file-input" id="customFile">
<label class="custom-file-label" for="customFile">Choose file...</label>
</div>
<span asp-validation-for="PublicationPdfUrl" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary float-right" />
<a asp-controller="CategoryItem" asp-action="Index" asp-route-categoryId="@Model.CategoryId" class="btn btn-outline-primary">Back to List</a>
</div>
</form>
</div>
</div>
This is my Edit View
@{
ViewData["Title"] = "Edit";
}
<h4>Edit</h4>
<h4>Content</h4>
<hr />
<div class="row">
<div class="col-md-10">
<form method="post" enctype="multipart/form-data" asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<input type="hidden" asp-for="CategoryId" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="HTMLContent" class="control-label"></label>
<textarea asp-for="HTMLContent" row="10" class="form-control"></textarea>
<span asp-validation-for="HTMLContent" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="VideoLink" class="control-label"></label>
<input asp-for="VideoLink" class="form-control" />
<span asp-validation-for="VideoLink" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PublicationPdfUrl" class="control-label"></label>
<div class="custom-file">
<input asp-for="PublicationPdfUrl" class="custom-file-input" id="customFile">
<label class="custom-file-label" for="customFile">Choose file...</label>
</div>
<span asp-validation-for="PublicationPdfUrl" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary float-right" />
<a asp-controller="CategoryItem" asp-action="Index" asp-route-categoryId="@Model.CategoryId" class="btn btn-outline-primary">Back to List</a>
</div>
</form>
</div>
</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
