使用框架:abp vnext
需求:定时从数据库取数据生成csv文件上传obs
在后台作业者模块新建一个定时任务并注册
记得一定要注册!
一开始笔者是想从本地生成文件,将内容写进去文件后上传,再删除清理内存:
var now = DateTime.Now.ToString("yyyMMdd");
string qianzhui = "reuse_detail_t";
string fileName = qianzhui + now + ".csv";
string filePath = Directory.GetCurrentDirectory() + @"/Upload/";
if (!Directory.Exists(filePath))
{
//不存在,则创建
Directory.Delete(filePath);
}
FileStream aFile = new FileStream(filePath + fileName, FileMode.OpenOrCreate);
using (StreamWriter sw = new StreamWriter(aFile, Encoding.UTF8))
{
foreach (var item in datas)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(item.Id.ToString() + "|");
///拼接字符串。。。
sw.WriteLine(stringBuilder.ToString());
}
}
HuaWeiOBS.PutObjet("bucketName", "objKey", aFile);
但此时上传文件会抛出异常
Cannot access a closed Stream
没错!文件流写完就关闭了,读取不了 ,于是只能把上传的引用放在这个地方
using (StreamWriter sw = new StreamWriter(aFile, Encoding.UTF8))
{
foreach (var item in datas)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(item.Id.ToString() + "|");
///拼接字符串。。。
sw.WriteLine(stringBuilder.ToString());
}
HuaWeiOBS.PutObjet("bucketName", "objKey", aFile);
}
做到这里其实已经差不多了,但是!此做法并没有清理生成的文件,还得去清除它,再加一个:
private void DeleteFile()
{
string filePath = Directory.GetCurrentDirectory() + @"/Upload/";
if (Directory.Exists(filePath))
{
foreach (string f in Directory.GetFileSystemEntries(filePath))
{
if (File.Exists(f))
{
//如果有子文件删除文件
File.Delete(f);
}
}
//删除空文件夹
Directory.Delete(filePath);
}
}
在定时任务执行时清理它:
using (var uow = LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>().Begin())
{
DeleteFile();
var oeHwDataManager = ServiceProvider.GetRequiredService<OeHwDataManager>();
await oeHwDataManager.UploadObsFileAsync();
await uow.CompleteAsync();
}
此方法第一次执行时没有任何问题,但是第二次执行时就会抛出异常:
System.IO.IOException
The process cannot access the file 'D:\wwwroot\Upload\xxx.csv' because it is being used by another process.
没错,按着这意思来看得关闭程序才能删除这个文件了,但这是不现实的;
所以笔者在想有没有办法能绕过写入文件,再读取文件流这一个步骤,就是说不用生成本地文件,我们直接生成一个流,将内容写进去,再以流形式上传obs。后来经过询问朋友和baidu,终于有了解决方案,使用内存流去进行此操作,但需要注意,MemoryStream是会占用服务器性能的,所以说,请按情况使用这方法。话不多说,直接贴代码:
private async Task CreateCsvFileAsync(List<HwData> datas)
{
byte[] bytes;
using (MemoryStream ms = new())
{
using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8))
{
foreach (var item in datas)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(item.Id.ToString() + "|");
///拼接字符串。。。
sw.WriteLine(stringBuilder.ToString());
}
//放在这里的原因是,出了StreamWriter后,也会抛异常Cannot access a closed Stream
//不要问我为什么出了这个using就关闭了,求你了,百度吧
bytes = new byte[ms.Length];
ms.Read(bytes, 0, bytes.Length);
}
}
HuaWeiOBS.PutObjet("bucketName", "objKey", new MemoryStream(bytes));
}
从数据库取出来的数据在这里我们已经转换成了byte[]对象,使用此对象一般不会有什么问题,也不会抛出奇奇怪怪的异常啦,后续将此对象转化为流就可以上传了,并且可以多次上传,比如需要“备份”,end。
如果对你有帮助,就请点个赞吧!
如果你需要引用此文章的内容,请标记出处哦!