Upload pliku w ASP.NET Core 1.0

Dzięki nowym funkcjonalnościom w ASP.NET Core 1.0 takim jak np. Tag Helpers upload plików wygląda troszeczkę inaczej w porównaniu do poprzednich wersji.

Zacznijmy od kodu widoku:
<form method="post" asp-action="Index" asp-controller="Recipe" enctype="multipart/form-data" role="form">
	<div class="form-group">
		<label class="btn btn-lg btn-primary" for="my-file-selector">
			<input id="my-file-selector" type="file" name="files" style="display: none;" multiple />
			Select Files...
		</label>
		<input class="btn btn-lg" type="submit" value="Upload!" />
	</div>
</form>
Tak więc po kolei. asp-action="Index" asp-controller="Recipe" – oznacza tyle, że po wysłaniu formularza wywoła się akcja „Index” z kontrolera „Recipe”.
<label class="btn btn-lg btn-primary" for="my-file-selector">
	<input id="my-file-selector" type="file" name="files" style="display: none;" multiple />
	Select Files...
</label>
tu zastosowałem trik polegający na tym, że ukrywamy brzydki przycisk „Wybierz plik…”, zastępując go dowolną, wybraną przez nas treścią. Dodatkową ważną kwestią jest tutaj atrybut name="files" – to właśnie taka nazwa zmiennej musi pojawić się jako parametr akcji „Index”. Kolejna rzecz – multiple. Ten atrybut dodano w HTML5 – w naszym przypadku umożliwia wybór wielu plików.

Teraz przejdźmy do Controllera:
public class RecipeController : Controller
{
	private readonly IHostingEnvironment _hostingEnvironment;

	public RecipeController(IHostingEnvironment hostingEnvironment)
	{
		_hostingEnvironment = hostingEnvironment;
	}

	// GET: /Recipe/
	public IActionResult Index()
	{
		return View();
	}

	// POST: /Recipe/Index
	[HttpPost]
	public async Task Index(IEnumerable files)
	{
		var recipes = Path.Combine(_hostingEnvironment.WebRootPath, "recipes");
		if (!Directory.Exists(recipes))
		{
			Directory.CreateDirectory(recipes);
		}

		foreach (var file in files)
		{
			var fileName = GetFileName(file);

			await file.SaveAsAsync(Path.Combine(recipes, fileName));
		}

		return View("RecipeUploaded");
	}
}


W konstruktorze użyto parametru IHostingEnvironment, który przechowuje m.in. ścieżkę do root folderu strony. Jak widać – wykorzystałem to do ustalenia docelowego folderu zuploadowanych plików. Jedna z metod Index przyjmuje parametr IEnumerable<IFormFile> files. IEnumerable – ponieważ użyliśmy wcześniej wspomnianego atrybutu multiple. IFormFile – dla input type="file" taki oto interfejs reprezentuje jeden obiekt pliku, który został wybrany w formularzu i przesłany. Implementacja metody GetFileName(file) nie jest pokazana, jednak jej najprostsza forma może wyglądać następująco:
private static string GetFileName(IFormFile file)
{
	return ContentDispositionHeaderValue
		.Parse(file.ContentDisposition)
		.FileName
		.Trim('"');
}
Dzięki temu pliki w folderze wwwroot\recipes będą miały taką samą nazwę jak pliki wybrane do uploadu. Czy to dobrze? Nie do końca 😉 Ale o tym kiedy indziej.

Post jest elementem serii wpisów dotyczących projektu CookBook realizowanego w ramach konkursu „Daj się poznać”.
DSP2016 logo RGB color-1

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *