using System; using System.IO; using System.Text; using System.Threading.Tasks; using Hncore.Infrastructure.Extension; using Microsoft.AspNetCore.Http; namespace Hncore.Infrastructure.CSV { public class CsvTemporaryFile : IDisposable { private string filePath = ""; private FileStream _fileStream; private StreamWriter _streamWriter; public CsvTemporaryFile() { var execDir = Path.GetDirectoryName(typeof(CsvTemporaryFile).Assembly.Location); string tempDir = Path.Combine(execDir, "temp", DateTime.Now.ToString("yyyyMMdd")); if (!Directory.Exists(tempDir)) { Directory.CreateDirectory(tempDir); } filePath = Path.Combine(tempDir, Guid.NewGuid().ToString()); _fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write); _streamWriter = new StreamWriter(_fileStream, Encoding.GetEncoding("GB2312")); _streamWriter.AutoFlush = true; } public void WriteLine(CsvRow row) { _streamWriter.WriteLine(row.ToString()); } public async Task ResponseAsync(HttpResponse httpResponse, string fileName) { httpResponse.ContentType = "application/octet-stream"; httpResponse.Headers.Add("Content-Disposition", $"attachment; filename={fileName.UrlEncode()}"); httpResponse.Headers.Add("X-Suggested-Filename", fileName.UrlEncode()); using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (BufferedStream bs = new BufferedStream(fs)) { byte[] buffer = new byte[4096]; int bytesRead; long total_read = 0; DateTime begin = DateTime.Now; TimeSpan ts = new TimeSpan(); while ((bytesRead = bs.Read(buffer, 0, buffer.Length)) > 0) { await httpResponse.Body.WriteAsync(buffer, 0, bytesRead); await httpResponse.Body.FlushAsync(); total_read += bytesRead; ts = DateTime.Now - begin; if (total_read / ts.TotalSeconds > 1024 * 1000) { await Task.Delay(1); } } } } } public void Dispose() { _streamWriter?.Dispose(); _fileStream?.Dispose(); if (File.Exists(filePath)) { File.Delete(filePath); } } } }