using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DW5S.WebApi
{
///
/// 文件操作接口
/// 可通过浏览器访问http://{baseurl}/upload地址预览文件
///
public class FileController : BaseController
{
ILogger Logger { get; set; }
///
/// 上传文件(随机生成文件名)
///
/// 表单文件集合
///
[HttpPost]
public async Task>> UploadWithRandomAsync(List files)
{
if (files.Count == 0) return Error>("请选择文件");
string uploadDir = "Upload";
string time = DateTime.Now.ToString("yyyyMMdd_HH");
string path = Path.Combine(AppContext.BaseDirectory, uploadDir, time);//子目录
Directory.CreateDirectory(path);
var result = new List();
foreach (var file in files)
{
var filename = Path.GetFileName(file.FileName);
if (string.IsNullOrWhiteSpace(filename)) continue;
var fileext = Path.GetExtension(filename).ToLower();
Directory.CreateDirectory(path);
//重新命名文件
var pre = DateTime.Now.ToString("yyyyMMddHHmmssfff");
var seed = BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0);
var after = new Random(seed).Next(1000, 9999);
var fileloadname = $"{pre}_{after}_{ProExt(fileext)}";
using (var stream = new FileStream(Path.Combine(path, fileloadname), FileMode.Create))
{
await file.CopyToAsync(stream);
}
string fileUrl = $"{uploadDir}/{time}/{fileloadname}";
result.Add(fileUrl);
}
return Success(result);
}
///
/// 上传文件(保留文件名)
///
/// 表单文件集合
/// 是否覆盖已经存在的本地文件
///
[HttpPost]
public async Task>> UploadAsync(List files, bool overwriteExisted = true)
{
if (files.Count == 0) return Error>("请选择文件");
string uploadDir = "Upload";
string time = DateTime.Now.ToString("yyyyMMdd_HH");
string path = Path.Combine(AppContext.BaseDirectory, uploadDir, time);//子目录
Directory.CreateDirectory(path);
var result = new List();
foreach (var file in files)
{
var filename = Path.GetFileName(file.FileName);
if (string.IsNullOrWhiteSpace(filename)) continue;
string localFile = Path.Combine(path, filename);
if (overwriteExisted)
{
using var stream = new FileStream(localFile, FileMode.Create);
await file.CopyToAsync(stream);
}
else
{
if (!System.IO.File.Exists(localFile))
{
using var stream = new FileStream(localFile, FileMode.Create);
await file.CopyToAsync(stream);
}
}
string fileUrl = $"{uploadDir}/{time}/{filename}";
result.Add(fileUrl);
}
return Success(result);
}
///
/// 文件下载
///
/// 文件相对路径
///
[HttpGet]
public IActionResult Download(string file)
{
if (string.IsNullOrWhiteSpace(file))
{
return NotFound("必须指定要下载的文件");
}
if (file.StartsWith("/"))
file = file.Substring(1);
string localFile = Path.Combine(AppContext.BaseDirectory, file);
try
{
if (!System.IO.File.Exists(localFile))
{
return NotFound($"文件[{localFile}]不存在");
}
string fileName = Path.GetFileName(localFile);
var fileStream = new FileStream(localFile, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, true); //异步读取文件
return File(fileStream, "application/octet-stream", fileName, true); //为true时,支持断点续传
}
catch (Exception ex)
{
Logger.Error(ex, $"文件[{localFile}]下载失败");
return NotFound($"文件[{localFile}]下载失败");
}
}
#region 校验文件类型
readonly string[] badext = { ".exe", ".msi", ".bat", ".com", ".sys", ".aspx", ".asax", ".ashx" };
private string ProExt(string ext)
{
if (string.IsNullOrWhiteSpace(ext)) return "";
if (badext.Contains(ext)) throw new Exception("危险文件");
if (ext.First() == '.') return ext;
return "." + ext;
}
#endregion
}
}