在現代Web應用程序中,文件上傳與下載是非常常見的功能。無論是用戶上傳頭像、文檔,還是下載報告、圖片,文件處理都是不可或缺的一部分。ASP.NET Core 提供了強大的工具和API,使得文件上傳與下載的實現變得簡單而高效。本文將詳細介紹如何在ASP.NET Core中實現文件上傳與下載功能。
在ASP.NET Core中,文件上傳通常通過HTML表單的<input type="file">元素來實現。用戶通過該元素選擇文件后,文件數據會通過HTTP POST請求發送到服務器。服務器端可以通過IFormFile接口來處理上傳的文件。
首先,我們需要在前端創建一個表單,允許用戶選擇文件并上傳。以下是一個簡單的HTML表單示例:
<form method="post" enctype="multipart/form-data" action="/Upload">
<div>
<label for="file">選擇文件:</label>
<input type="file" id="file" name="file" />
</div>
<div>
<button type="submit">上傳</button>
</div>
</form>
在這個表單中,enctype="multipart/form-data"是必須的,它告訴瀏覽器將表單數據編碼為多部分表單數據,以便能夠上傳文件。
在ASP.NET Core中,我們可以通過控制器來處理文件上傳。以下是一個簡單的控制器示例:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;
public class UploadController : Controller
{
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
if (file == null || file.Length == 0)
{
return Content("文件未選擇或文件為空");
}
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads", file.FileName);
using (var stream = new FileStream(path, FileMode.Create))
{
await file.CopyToAsync(stream);
}
return Content("文件上傳成功");
}
}
在這個控制器中,我們定義了一個Upload方法,它接收一個IFormFile類型的參數file。IFormFile接口提供了訪問上傳文件的方法和屬性。
file.FileName:獲取上傳文件的文件名。file.Length:獲取上傳文件的大小。file.CopyToAsync(stream):將上傳文件的內容復制到指定的流中。在這個示例中,我們將上傳的文件保存到wwwroot/uploads目錄中。wwwroot是ASP.NET Core中用于存放靜態文件的默認目錄。
文件上傳功能雖然簡單,但也存在一些安全隱患。以下是一些常見的安全問題和解決方案:
為了防止用戶上傳惡意文件,我們應該對上傳的文件類型進行驗證??梢酝ㄟ^檢查文件的擴展名或MIME類型來實現。
var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif" };
var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (!allowedExtensions.Contains(fileExtension))
{
return Content("不支持的文件類型");
}
為了防止用戶上傳過大的文件,我們可以限制上傳文件的大小??梢酝ㄟ^配置IFormFile的Length屬性來實現。
var maxFileSize = 5 * 1024 * 1024; // 5MB
if (file.Length > maxFileSize)
{
return Content("文件大小超過限制");
}
為了防止文件名中包含惡意字符或路徑遍歷攻擊,我們應該對文件名進行清理。
var safeFileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads", safeFileName);
除了基本的文件上傳功能,我們還可以實現一些擴展功能,例如:
允許用戶一次上傳多個文件??梢酝ㄟ^在表單中使用<input type="file" multiple>來實現。
<form method="post" enctype="multipart/form-data" action="/Upload">
<div>
<label for="files">選擇文件:</label>
<input type="file" id="files" name="files" multiple />
</div>
<div>
<button type="submit">上傳</button>
</div>
</form>
在控制器中,我們可以使用IFormFileCollection來處理多個文件。
[HttpPost]
public async Task<IActionResult> Upload(List<IFormFile> files)
{
foreach (var file in files)
{
if (file.Length > 0)
{
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads", file.FileName);
using (var stream = new FileStream(path, FileMode.Create))
{
await file.CopyToAsync(stream);
}
}
}
return Content("文件上傳成功");
}
在文件上傳過程中,顯示上傳進度可以提升用戶體驗??梢酝ㄟ^JavaScript和AJAX來實現。
<form id="uploadForm" method="post" enctype="multipart/form-data" action="/Upload">
<div>
<label for="file">選擇文件:</label>
<input type="file" id="file" name="file" />
</div>
<div>
<button type="submit">上傳</button>
</div>
</form>
<div id="progress"></div>
<script>
document.getElementById('uploadForm').addEventListener('submit', function (e) {
e.preventDefault();
var formData = new FormData(this);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
document.getElementById('progress').innerHTML = '上傳進度: ' + percentComplete + '%';
}
});
xhr.open('POST', '/Upload', true);
xhr.send(formData);
});
</script>
文件下載是指用戶從服務器獲取文件的過程。在ASP.NET Core中,我們可以通過返回FileResult來實現文件下載。
以下是一個簡單的控制器示例,演示如何實現文件下載:
using Microsoft.AspNetCore.Mvc;
using System.IO;
public class DownloadController : Controller
{
public IActionResult Download(string fileName)
{
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads", fileName);
if (!System.IO.File.Exists(path))
{
return NotFound();
}
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
stream.CopyTo(memory);
}
memory.Position = 0;
return File(memory, GetContentType(path), Path.GetFileName(path));
}
private string GetContentType(string path)
{
var types = GetMimeTypes();
var ext = Path.GetExtension(path).ToLowerInvariant();
return types[ext];
}
private Dictionary<string, string> GetMimeTypes()
{
return new Dictionary<string, string>
{
{".txt", "text/plain"},
{".pdf", "application/pdf"},
{".doc", "application/vnd.ms-word"},
{".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
{".xls", "application/vnd.ms-excel"},
{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
{".png", "image/png"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".gif", "image/gif"},
{".csv", "text/csv"}
};
}
}
在這個控制器中,我們定義了一個Download方法,它接收一個fileName參數。首先,我們檢查文件是否存在。如果文件存在,我們將其讀取到內存流中,并返回FileResult。
File(memory, GetContentType(path), Path.GetFileName(path)):返回一個FileResult,其中memory是文件內容,GetContentType(path)是文件的MIME類型,Path.GetFileName(path)是文件的名稱。文件下載功能也存在一些安全隱患。以下是一些常見的安全問題和解決方案:
為了防止路徑遍歷攻擊,我們應該對文件名進行驗證。
var safeFileName = Path.GetFileName(fileName);
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads", safeFileName);
為了防止未經授權的用戶下載文件,我們可以對文件訪問進行權限控制。
if (!User.IsInRole("Admin"))
{
return Forbid();
}
除了基本的文件下載功能,我們還可以實現一些擴展功能,例如:
在文件下載過程中,顯示下載進度可以提升用戶體驗??梢酝ㄟ^JavaScript和AJAX來實現。
<a id="downloadLink" href="/Download?fileName=example.pdf">下載文件</a>
<div id="progress"></div>
<script>
document.getElementById('downloadLink').addEventListener('click', function (e) {
e.preventDefault();
var xhr = new XMLHttpRequest();
xhr.open('GET', this.href, true);
xhr.responseType = 'blob';
xhr.addEventListener('progress', function (e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
document.getElementById('progress').innerHTML = '下載進度: ' + percentComplete + '%';
}
});
xhr.onload = function () {
if (this.status === 200) {
var blob = this.response;
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'example.pdf';
link.click();
}
};
xhr.send();
});
</script>
如果用戶需要下載多個文件,我們可以將這些文件壓縮成一個ZIP文件后再提供下載。
using System.IO.Compression;
public IActionResult DownloadZip()
{
var files = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads"));
var memory = new MemoryStream();
using (var archive = new ZipArchive(memory, ZipArchiveMode.Create, true))
{
foreach (var file in files)
{
var entry = archive.CreateEntry(Path.GetFileName(file));
using (var entryStream = entry.Open())
using (var fileStream = new FileStream(file, FileMode.Open))
{
fileStream.CopyTo(entryStream);
}
}
}
memory.Position = 0;
return File(memory, "application/zip", "files.zip");
}
在ASP.NET Core中實現文件上傳與下載功能并不復雜,但需要注意一些安全性問題。通過本文的介紹,你應該能夠掌握如何在ASP.NET Core中實現文件上傳與下載,并且了解如何擴展這些功能以滿足不同的需求。希望本文對你有所幫助!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。