简体   繁体   中英

Upload and View Files ASP.NET MVC 5

I have this code:

    [HttpPost]
    public ActionResult Create(Knowledgebase KB, HttpPostedFileBase file)
    {
        var KBFilePath = "";
        if (ModelState.IsValid)
        {
            if (file.ContentLength > 0)
            {
                var fileName = Path.GetFileName(KB.KnowledgebaseTitle);
                var path = Path.Combine(Server.MapPath("~/Resources/KBArticles"), fileName + ".pdf");
                KBFilePath = path;
                file.SaveAs(path);
            }
            KB.KnowledgebaseLink = KBFilePath;
            db.Knowledgebases.Add(KB);
            db.SaveChanges();
            return RedirectToAction("Index", "Home");
        }

        else
        {
            return View();
        }

The link is the filepath which is stored in the DB which starts with C:/

On another page I can view the contents of the record. When I click on the link to which its saved on the C:/, Chrome says 'Failed to load local resource'. I am saving into the Resources folder which is part of my ASP.NET app directory. Anyway around this?

EDIT The page is served from this View:

public ActionResult Suggestions(String Tag)
{
      return View();
}

EDIT 2 - I put the changes in my view:

@{
string tag = "<td><a href=" + "~/Content/Files/" + ">" + item.Title.Replace(" ", "") + ".pdf" + "</a>" + "</td>";
 }
 @Html.Raw(tag)

The requested file in the browser address bar is

http://localhost:62165/Incident/~/Content/Files/

Now I get a HTTP Error 404.0 Not Found error

This is a full example that shows how to upload files and put them available for download through links.

Create an empty MVC Project. I use MVC 4 but it should work with MVC 5.

Controller:

In the HomeController we are going to have a single action Index that will show the list of files available for download and the option for uploading new files.

Action Index GET:

  • Locate the path to 'Content/Files/'.
  • Get the list of all files in that folder.
  • Use that list as the model of the Index view.

Action Index POST:

  • Locate the path to 'Content/Files/'.
  • Create a temporary array to store the content of the file.
  • Read the content to the buffer.
  • Write the content to a file in folder 'Content/Files/'.

Code:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var path = Server.MapPath("~/Content/Files/");

        var dir = new DirectoryInfo(path);

        var files = dir.EnumerateFiles().Select(f => f.Name);

        return View(files);
    }

    [HttpPost]
    public ActionResult Index(HttpPostedFileBase file)
    {
        var path = Path.Combine(Server.MapPath("~/Content/Files/"), file.FileName);

        var data = new byte[file.ContentLength];
        file.InputStream.Read(data, 0, file.ContentLength);

        using (var sw = new FileStream(path, FileMode.Create))
        {
            sw.Write(data, 0, data.Length);
        }

        return RedirectToAction("Index");
    }

}

View:

In the view we need to generate a list with links to the files. Here we need to take care of file names that contains spaces and replace them with '%20'.

The form to upload a file is simple. Just an input tag to get the file and one button to send the form.

@model IEnumerable<string>

@{
    ViewBag.Title = "Index";
}

<h2>Files</h2>

<ul>
    @foreach (var fName in Model)
    {
        var name = fName;
        var link = @Url.Content("~/Content/Files/") + name.Replace(" ", "%20");

        <li>
            <a href="@link">@name</a>
        </li>
    }
</ul>

<div>
    @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <input type="File" name="file" id="file" value="Choose File"/>
        <button type="submit">Upload</button>
    }
</div>

The result should be:

索引视图

Try to save the files in Content folder. You can create a sub folder Content/Files. Put you files there. Then generate the links like:

<a href="~/Content/Files/file1.pdf">File1</a>

or use the download attribute if you want to download directly:

<a href="~/Content/Files/file1.pdf" download>File1</a> .

Most web servers are configured to deny requests for content outside the content folder. This can be modified in the config file but is easier (and safer) if you use the content folder. This is based on my experience, if someone think that I'm wrong please let me know to fix my answer. I'm always glad to learn something new.

EDIT 1: How to build the a tag dynamically

In the view you need a string variable link that holds the text of the link you want to show and another variable path to hold the path (maybe both are loaded from db in the controller). Then you can build the tag manually like this:

@{
    string tag = "<a href=" + path + ">" + link + "</a>";
}

@Html.Raw(tag)

EDIT 2: Dealing with spaces in Url.

You need to use Html.Content to get the right relative Url.

@{
    string link = item.Title;
    string path = Url.Content("~/Content/Files/") + link.Replace(" ", "%20") + ".pdf";
    string tag = "<a href=" + path + ">" + link + "</a>";
}

@Html.Raw(tag)

First the Create View <

<div class="form-group"> @Html.LabelFor(model => model.ImageData, new { @class = "control-label col-md-2" }) 
  <div class="col-md-10"> <input name="Image" type="file" /> 
    @Html.ValidationMessageFor(model => model.ImageData) 
  </div> 
</div>

Then the Controller Create Action

public ActionResult Create(ArtWork artwork, HttpPostedFileBase image) { 
  if (ModelState.IsValid) { 
    if (image != null) { //attach the uploaded image to the object before saving to Database 
      artwork.ImageMimeType = image.ContentLength; 
      artwork.ImageData = new byte[image.ContentLength]; 
      image.InputStream.Read(artwork.ImageData, 0, image.ContentLength); //Save image to file 
      var filename = image.FileName; 
      var filePathOriginal = Server.MapPath("/Content/Uploads/Originals"); 
      var filePathThumbnail = Server.MapPath("/Content/Uploads/Thumbnails"); 
      string savedFileName = Path.Combine(filePathOriginal, filename); 
      image.SaveAs(savedFileName); //Read image back from file and create thumbnail from it 
      var imageFile = Path.Combine(Server.MapPath("~/Content/Uploads/Originals"), filename); 

      using (var srcImage = Image.FromFile(imageFile)) 
      using (var newImage = new Bitmap(100, 100)) 
      using (var graphics = Graphics.FromImage(newImage)) 
      using (var stream = new MemoryStream()) { 
        graphics.SmoothingMode = SmoothingMode.AntiAlias; 
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; 
        graphics.DrawImage(srcImage, new Rectangle(0, 0, 100, 100)); 
        newImage.Save(stream, ImageFormat.Png); 
        var thumbNew = File(stream.ToArray(), "image/png"); 
        artwork.ArtworkThumbnail = thumbNew.FileContents; 
      } 
    } 

    //Save model object to database 
    db.ArtWorks.Add(artwork); 
    db.SaveChanges(); 
    return RedirectToAction("Index"); 
  } 
  return View(artwork); 
}

Then a get Image or GetThumbnail method

public FileContentResult GetThumbnailImage(int artworkId) { 
  ArtWork art = db.ArtWorks.FirstOrDefault(p => p.ArtWorkId == artworkId); 
  if (art != null) { 
    return File(art.ArtworkThumbnail, art.ImageMimeType.ToString()); 
  } else { 
    return null; 
  } 
}

And here for the display in the view

<td> <img src="@Url.Action("GetThumbnailImage", "Artwork", new { Model.ArtWorkId })" alt="Artwork Image" /> </td>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM