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 Microsoft.Extensions.Logging;
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
    {
        private ILogger logger;
        public FileController(ILogger logger)
        {
            this.logger = logger;
        }
        /// 
        /// 上传文件(随机生成文件名)
        /// 
        /// 表单文件集合
        /// 
        [HttpPost]
        public async Task>> UploadWithRandom(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>> Upload(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.LogError(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
    }
}