为啥有这个话题,小编最近有个下载数据量的报表需求,实现原理是新开一个线程,用这个线程去按照分页的方式整合数据,整合完成后生成Excel文件,前台会有个方法来定时扫描这个文件,如果文件存在导出。功能实现了,但是在下载数据量大的情况报错了,明明找到了文件下载不下来,翻阅了一下错误原因,原来文件太大了,生成文件太慢导致文件是占用状态。怎么解决,在判断文件是否存在的情况下再判断一下是否被占用,有两种方法,如下:.
一、WIN32 API调用
[DllImport("kernel32.dll")]public static extern IntPtr _lopen(string lpPathName, int iReadWrite);[DllImport("kernel32.dll")]public static extern bool CloseHandle(IntPtr hObject);public const int OF_READWRITE = 2;public const int OF_SHARE_DENY_NONE = 0x40;public static readonly IntPtr HFILE_ERROR = new IntPtr(-1);public static bool IsOccupied(string fileFullNmae){if (!File.Exists(fileFullNmae)) return false;IntPtr vHandle = _lopen(fileFullNmae, OF_READWRITE | OF_SHARE_DENY_NONE);var flag = vHandle == HFILE_ERROR;CloseHandle(vHandle);return flag;}static void Main(){string pathname = "d:\\Temp\\test.xlsx";var rel = IsOccupied(pathname);}//rel结果如果占用为true,否则为false
二、通过文件流方式打开测试
//判断文件是否占用public static bool IsFileInUse(string fileName){bool inUse = true;FileStream fs = null;try{fs = new FileStream(fileName, FileMode.Open, FileAccess.Read,FileShare.None);inUse = false;}catch{}finally{if (fs != null)fs.Close();}return inUse;//true表示正在使用,false没有使用}//调用static void Main(){string pathname = "d:\\Temp\\test.xlsx";var rel = IsFileInUse(pathname);}//rel结果如果占用为true,否则为false
结语
这两种方法推荐使用第二种方法,第一种方法如果跨平台可能会有问题。网上还有其他方法,比如执行copy文件等,从实用性还是觉得这两种方法比较好。