Загрузка и просмотр файлов ASP.NET MVC 5
У меня есть этот код:
[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();
}
Ссылка - это путь к файлу, который хранится в БД, который начинается с C:/
На другой странице я могу просмотреть содержимое записи. Когда я нажимаю ссылку, на которую она была сохранена на C:/, Chrome говорит: "Не удалось загрузить локальный ресурс". Я сохраняю в папке Ресурсы, которая является частью моего каталога приложений ASP.NET. Во всяком случае, вокруг этого?
ИЗМЕНИТЬ
Страница открывается из этого представления:
public ActionResult Suggestions(String Tag)
{
return View();
}
ИЗМЕНИТЬ 2 - Я ввел изменения в свое мнение:
@{
string tag = "<td><a href=" + "~/Content/Files/" + ">" + item.Title.Replace(" ", "") + ".pdf" + "</a>" + "</td>";
}
@Html.Raw(tag)
Запрошенный файл в адресной строке браузера
http://localhost:62165/Incident/~/Content/Files/
Теперь я получаю ошибку HTTP Error 404.0 Not Found
Ответы
Ответ 1
Попробуйте сохранить файлы в папке "Содержимое". Вы можете создать подпапку Content/Files. Поместите туда файлы. Затем создайте ссылки как:
<a href="~/Content/Files/file1.pdf">File1</a>
или используйте атрибут загрузки, если вы хотите напрямую загрузить:
<a href="~/Content/Files/file1.pdf" download>File1</a>
.
Большинство веб-серверов настроены на отклонение запросов на контент вне папки содержимого. Это можно изменить в файле конфигурации, но проще (и безопаснее), если вы используете папку содержимого. Это основано на моем опыте, если кто-то подумает, что я не прав, сообщите мне, чтобы исправить мой ответ. Я всегда рад узнать что-то новое.
РЕДАКТИРОВАТЬ 1: Как динамически построить тег a
В представлении вам понадобится строковая переменная link
, которая содержит текст ссылки, которую вы хотите показать, и другую переменную path
для хранения пути (возможно, оба они загружаются из db в контроллере). Затем вы можете создать тег вручную следующим образом:
@{
string tag = "<a href=" + path + ">" + link + "</a>";
}
@Html.Raw(tag)
РЕДАКТИРОВАТЬ 2: Работа с пробелами в URL.
Вам нужно использовать Html.Content
, чтобы получить правильный относительный 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)
Ответ 2
Это полный пример, который показывает, как загружать файлы и размещать их для загрузки через ссылки.
Создайте пустой MVC-проект.
Я использую MVC 4, но он должен работать с MVC 5.
Контроллер:
В HomeController
у нас будет одно действие Index
, в котором будет отображаться список файлов, доступных для загрузки, и возможность загрузки новых файлов.
Действие Index
GET:
- Найдите путь к "Контент/Файлы/".
- Получить список всех файлов в этой папке.
- Используйте этот список в качестве модели представления
Index
.
Действие Index
POST:
- Найдите путь к "Контент/Файлы/".
- Создайте временный массив для хранения содержимого файла.
- Прочитайте содержимое в буфере.
- Введите содержимое в файл в папке "Содержимое/Файлы/".
код:
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");
}
}
Вид:
В представлении нам нужно сгенерировать список со ссылками на файлы. Здесь нам нужно позаботиться о именах файлов, содержащих пробелы, и заменить их на "%20".
Форма для загрузки файла проста. Просто введите тег, чтобы получить файл и одну кнопку, чтобы отправить форму.
@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>
Результат должен быть:
![Index view]()
Ответ 3
Сначала создайте представление <
<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>
Затем контроллер 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);
}
Затем метод get Image или GetThumbnail
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;
}
}
И вот для отображения в представлении
<td> <img src="@Url.Action("GetThumbnailImage", "Artwork", new { Model.ArtWorkId })" alt="Artwork Image" /> </td>