0

I am a beginner in ASP.Net MVC 5 and I want to know how to upload file in database and the display them to the user. I saw numerous example on internet related to above question. But all talks about putting file in some solution folder. But I want to upload file to database and be able to retrieve it in "Details View".

Issue: I am able to upload file in Database, but I am not sure how to Display the file link to user. Clicking on which user should be able to view/download the uploaded file. Below is my attempt.

Model:

public class File
{
    public int Id { get; set; }
    [StringLength(255)]
    public string FileName { get; set; }
    public byte[] Content { get; set; }
}

Controller:

// GET: FileUpload
public ActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(File file, HttpPostedFileBase upload)
{
    try
    {
        if (ModelState.IsValid)
        {
            if (upload != null && upload.ContentLength > 0)
            {
                var tempfile = new File
                {
                    FileName = System.IO.Path.GetFileName(upload.FileName),
                };
                using (var reader = new System.IO.BinaryReader(upload.InputStream))
                {
                    tempfile.Content = reader.ReadBytes(upload.ContentLength);
                }
                file.Content = tempfile.Content;
            }
            _context.Files.Add(file);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }
    }
    catch (RetryLimitExceededException /* dex */)
    {
        //Log the error (uncomment dex variable name and add a line here to write a log.
        ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
    }
    return View(file);
}

public ActionResult Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    File f1 = _context.Files.Where(f => f.Id == id).SingleOrDefault();
    if (f1 == null)
    {
        return HttpNotFound();
    }
// NOT SURE WHAT TO HERE
    return View(f1);
}

View: Details.chtml file

@model fileupload.Models.File
<h4>File</h4>
@* NOT SURE HOW TO HANDLE THE FILE LINK HERE*@

So, In the database I can see some binary content entry in "Content" Column. But I am not sure how can I display some link in the detail section. I want to display the file link in the details view. Clicking on which the file will get downloaded or something like preview. Kindly guide me.

EDIT 1

public FileContentResult Download(int id)
{
    var file = _context.Files.First(f => f.Id == id);
    var fileRes = new FileContentResult(file.Content.ToArray(), "application/pdf");
    fileRes.FileDownloadName = file.FileName;
    return fileRes;
}
Unbreakable
  • 7,776
  • 24
  • 90
  • 171
  • So you have an existing detail view? You just need to replace each entries to a URL that allows you to download your file. I'm guessing that would be a URL to another action method – Nick.Mc Aug 06 '17 at 22:42
  • I got the content in Binary format in the details controller action. Now what next. I mean I need to provide a link in the details section. If that link is clicked then the file should either get downloaded. If nothing, then as I have the binary formatted file in details controller action. How can I show/render it in Details View. – Unbreakable Aug 06 '17 at 22:44
  • Even if it will be another URL Action method. How can I allow downloading on button click. I am newbie. Kindly guide me. – Unbreakable Aug 06 '17 at 22:46
  • If any more clarity is required about my question. Kindly ask me. – Unbreakable Aug 06 '17 at 22:53
  • Sorry I named it wrong - do you have an existing _index_ view? You need to alter that so that instead of going to a detail view, it calls a controller action that downloads the file. This page has some code that has an example of a controller that downloads a file from a database. Each line of your index page has the correct link (i.e. passes in the correct id) to this controller. https://forums.asp.net/t/1708745.aspx?Download+uploaded+files+from+database – Nick.Mc Aug 06 '17 at 23:07
  • Thank you so much. I added the download method, mentioned in the link. And I uploaded a PDF and it downloaded it but the file downloaded is in some other format. I typed below code. ' var fileRes = new FileContentResult(file.Content.ToArray(), "application/pdf");' – Unbreakable Aug 06 '17 at 23:15
  • Added an EDIT section in the original question. Can you kindly see once. – Unbreakable Aug 06 '17 at 23:17
  • not too sure where to go from "some other format". Does it have the correct extension? How do you know it's another format? Have you used the correct id? Is the file size the same or different? – Nick.Mc Aug 06 '17 at 23:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/151223/discussion-between-unbreakable-and-nick-mcdermaid). – Unbreakable Aug 06 '17 at 23:20

2 Answers2

0

Assuming your code in your controller is correctly populating your model, you simply need base64 encode the image and display that.

@{
    var encodedImage = Convert.ToBase64String(Model.Content);
    var embeddedImage = $"data:image/png;base64,{encodedImage}";
}

<img src="@embeddedImage" />

Take a look at this question as well: MVC How to display a byte array image from model

tj-cappelletti
  • 1,774
  • 12
  • 19
0

Add below code in model :

            public string imagePath { get; set; }

            [Display(Description = "imgfile")]
            [RegularExpression(@"([a-zA-Z0-9()\s_\\.\-:!@#$%^&])+(.png|.jpg|.gif|.bmp|.tiff|.PNG|.JPG|.GIF|.BMP|.TIFF)$", ErrorMessage = "Only Image files allowed.")]
            public HttpPostedFileBase imgfile { get; set; }

In controller (This will validate your image for maore than 1mb from your action, if u want to validate it before post you can google it for jquery validations) :

if (userRegObj != null && userRegObj.imgfile != null && userRegObj.imgfile.FileName != null && userRegObj.imgfile.ContentLength > 1024000)//1 MB
                    {
                        TempData["msg"] = "danger~Profile Picture Should be Less Than 1 MB";
                        if (userRegObj.Id <= 0)
                        {
                            return View(userRegObj);
                        }
                        return RedirectToAction("Action", "Controller", new { id = userRegObj.Id });
                    }



                    else if (userRegObj != null && userRegObj.imgfile != null && userRegObj.imgfile.FileName != null)
                    {
                        string path = Path.Combine(Server.MapPath("~/Media/ProfilePics"), Path.GetFileName(userRegObj.imgfile.FileName)); // folder to save images
                        userRegObj.imagePath = Path.GetFileName(userRegObj.imgfile.FileName);
                        userRegObj.imgfile.SaveAs(path);
                    }

In view (This code will help you if your model having an image then it will show the image in the upload section else it will show a default image as you want to manage yourself) :

@if (Model != null && Model.Id>0 &&Model.imagePath!=null)
                                        {
                                            <div class="form-group">
                                                <label for="exampleInputEmail1">Upload Your Image:<br /><small>(Width:155, Height:155)</small></label>
                                                <span class="imageupld">
                                                    <img src="@Url.Content("~/Media/ProfilePics/"+Model.imagePath)" alt="obsequium" id="profilepic"  style="margin-top:8.5px" />
                                                </span>
                                                <span class="file-up" style="overflow:hidden;">
                                                    <span class="pic" id="p">@Model.imagePath</span>
                                                    @Html.TextBoxFor(m => m.imgfile, new { @class = "profilepic", type = "file", data_value = "pic", tabindex = 17, accept = "image/*", id = "picVal", @onchange = "checkImage()" })
                                                    @Html.ValidationMessageFor(m => m.imgfile, "", new { @class = "text-red", id = "imgVal" })
                                                </span>
                                            </div>
                                        }
                                        else if (Model != null && Model.Id>0 && Model.imagePath == null )
                                        {
                                        <div class="form-group">
                                            <label for="exampleInputEmail1">Upload Your Image:<br /><small>(Width:155, Height:155)</small></label>
                                            <span class="imageupld">
                                                <img src="@Url.Content("~/Content/Template/")images/imgupload.png" alt="obsequium" id="profilepic" style="margin-top:8.5px">
                                            </span>
                                            <span class="file-up" style="overflow:hidden;">
                                                <span class="pic">Upload Image</span>
                                                @Html.TextBoxFor(m => m.imgfile, new { @class = "profilepic", type = "file", data_value = "pic", tabindex = 17, accept = "image/*", id = "picVal", @onchange = "checkImage()" })
                                                @Html.ValidationMessageFor(m => m.imgfile, "", new { @class = "text-red", id = "imgVal" })
                                            </span>
                                        </div>
                                    }
Luqman
  • 139
  • 2
  • 15