Asp.net core 學習筆記 ( upload/download files 文件上傳與下載 )


更新 :  2018-01-22 

之前漏掉了一個 image 優化, 就是 progressive jpg 

refer : 

http://techslides.com/demos/progressive-test.html (online test)

http://magick.codeplex.com/discussions/450804 (Magick)

https://www.imgonline.com.ua/eng/make-jpeg-progressive-without-compression-result.php (online convert)

https://developers.google.com/speed/docs/insights/OptimizeImages (google 優化圖片指南)

image.Settings.SetDefine(MagickFormat.Jpeg, "sampling-factor", "4:2:0");
image.Format = MagickFormat.Pjpeg; // 轉換成 progressive jpg 
image.Strip(); //這句會把圖片的所有 EXIF 洗掉
image.Quality = 85;

 

 

 

2017-09-25 

refer : https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads

https://www.codeproject.com/Articles/1203408/Upload-Download-Files-in-ASP-NET-Core

這里只說說小文件上傳. 

先看看前端 js 代碼 

<input id="inputFile" type="file" />
<script>
    document.getElementById('inputFile').addEventListener('change', (e) => {        
        let files = e.target.files;        
        let formData = new FormData();
        formData.append("file", files[0]);
        let http = new XMLHttpRequest();
        http.open('POST', '/upload-file', true);
        http.send(formData); 
    }, false); 
</script>

如果要上傳多個文件就 append 多幾個就是了 

c# 

public class UploadFileData
{
    public IFormFile file { get; set; }
}

[Area("Web")]
public class UploadController : Controller
{
    public UploadController(
            IHostingEnvironment environment
    )
    {
        this.environment = environment;
    }

    private IHostingEnvironment environment { get; set; }
        
    [HttpPost("upload-file")]
    public async Task<IActionResult> uploadFile(UploadFileData data)
    {
        var allFiles = Request.Form.Files; // 多文件的話可以直接從 form 拿到完, 或則設置成 List<IFormFile> 就可以了
        var root = environment.WebRootPath;
        var extension = Path.GetExtension(data.file.FileName);
        var guid = Guid.NewGuid().ToString();
        var fullPath = $@"{root}\images\{guid + extension}";
        using (FileStream stream = new FileStream(fullPath, FileMode.Create))
        {
            await data.file.CopyToAsync(stream);
        } 
        return Ok();
    }
    [Route("upload")]
    public async Task<IActionResult> Index()
    {
        return View();
    }
}

上面的是最簡單的版本,創建 file 然后把 upload file stream 寫入 

如果是想直接使用 stream 也是可以 

using (var memoryStream = new MemoryStream())
{
    await model.file.CopyToAsync(memoryStream);
    memoryStream.Seek(0, SeekOrigin.Begin);
    new FileExtensionContentTypeProvider().TryGetContentType(model.file.FileName, out string contentType);

    await EmailService.SendAsync(
        recipients: BusinessConfig.contactEmailHandler,
        subject: "Contact form from website",
        templatePath: "~/Email/Contact/Index.cshtml",
        model: model,
        attachs: new List<Attachment> { new Attachment(memoryStream, model.file.FileName, contentType ?? "application/octet-stream") }
    );
}

需要注意的是寫入 stream 后, 如果要讀取 stream 記得, Seek 一下. 

 

還有一個常用的場景是, 上傳圖片要做 EXIF 處理. 

可以用 Magick.NET 目前支持 core, 不過呢, 好像只支持 window 場景. 如果你不是 windows 可能要在等等或則用其它插件.

Magick 需要設置, 參考 : https://magick.codeplex.com/documentation

MagickAnyCPU.CacheDirectory = @"C:\MyProgram\MyTempDir";
MagickNET.SetTempDirectory(@"C:\MyProgram\MyTempFiles");
例子
using (var stream = data.file.OpenReadStream())
using (MagickImage image = new MagickImage(stream))
{
    ExifProfile profile = image.GetExifProfile();
    image.Settings.SetDefine(MagickFormat.Jpeg, "sampling-factor", "4:2:0");
    image.Strip(); //這句會把圖片的所有 EXIF 洗掉
    image.Quality = 85;

    if (profile != null)
    {
        ExifValue orientation = profile.Values.SingleOrDefault(v => v.Tag == ExifTag.Orientation);
        if (orientation != null)
        {
            int orientationInt = Convert.ToInt32(orientation.Value);
            if (orientationInt == 6)
            {
                image.Rotate(90);
            }
            else if (orientationInt == 8)
            {
                image.Rotate(-90);
            }
            else if (orientationInt == 8)
            {
                image.Rotate(180);
            }
        }
        image.Write(fullPath);
    }
    else
    {
        image.Write(fullPath);
    }
}

很簡單吧.

再來一個 zip 的 

using (var stream = data.file.OpenReadStream())
using (var compressedFileStream = new FileStream($@"{root}\images\{guid}.zip", FileMode.Create))
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false))
{
    var zipEntry = zipArchive.CreateEntry(data.file.FileName);
    using (var zipEntryStream = zipEntry.Open())
    {
        stream.CopyTo(zipEntryStream);
    }
}

core 支持 ZipArchive 哦

 

下載也很容易 

public UploadController(
        IHostingEnvironment environment,
        IContentTypeProvider contentTypeProvider
)
{
    this.environment = environment;
    this.contentTypeProvider = contentTypeProvider;
}

private IHostingEnvironment environment { get; set; }
private IContentTypeProvider contentTypeProvider { get; set; }
        
[HttpGet("download-file")]
public FileResult downloadFile(string name, string display)
{
    string contentType;
    contentTypeProvider.TryGetContentType(name, out contentType);
    HttpContext.Response.ContentType = contentType;
    string path = environment.WebRootPath + @"\images\" + name; // 注意哦, 不要像我這樣直接使用客戶端的值來拼接 path, 危險的 
    FileContentResult result = new FileContentResult(System.IO.File.ReadAllBytes(path), contentType)
    {
        FileDownloadName = display
    };
   // return File("~/excels/report.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "report.xlsx"); // 返回 File + 路徑也是可以, 這個路徑是從 wwwroot 走起
   // return File(await System.IO.File.ReadAllBytesAsync(path), same...) // 或則我們可以直接返回 byte[], 任意從哪里獲取都可以.
return result; }

html

<a href="/download-file?name=123.jpg&display=aaa.jpg" download  >download</a>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM