如何在下载前检查zip文件是否未被其他进程使用
本文关键字:其他 进程 是否 文件 下载 zip 检查 | 更新日期: 2023-09-27 18:01:30
我正在编写一个Windows服务,从服务器上的Uri路径收集zip文件。我遇到的问题是,当我的服务试图收集zip文件时,它仍然在服务器上被写入。如果我在调用下载文件之前放一个Thread.Sleep(15000)
,它就能正常工作。在处理视频报警时,这种延迟是不可接受的。如果可能的话,我更愿意在while循环中添加检查,以便在调用下载函数之前查看文件是否准备好从服务器URI下载。这可能吗?
我正在使用异步WebClient下载zip文件:
internal void DownloadZippedFile(string eventId)
{
try
{
Logger.LogInformation("Extracing Video for event: " + eventId);
using (WebClient webClient = new WebClient())
{
string urlPath = sureViewZipHost + "/archiveevent?user=" + sureViewUserId + "&password=" + sureViewPassword + "&event=" + eventId;
string tempPath = Path.GetTempPath();
long lReceived = 0;
long lTotal = 0;
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted);
webClient.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
{
Logger.LogInformation("downloaded {0} of {1} bytes. {2}% complete", e.BytesReceived, e.TotalBytesToReceive, e.ProgressPercentage);
// Assign to outer variables to allow busy-wait to check.
lReceived = e.BytesReceived;
lTotal = e.TotalBytesToReceive;
};
webClient.DownloadFileAsync(new Uri(urlPath), tempPath + "//" + eventId + ".zip",eventId);
}
}
catch (Exception ex)
{
Logger.LogError("Error extracting Video " + ex.Message);
}
}
使用上面的代码永远不会抛出异常。我通过打开部分下载的zip文件发现了这个问题,它包含:
400 BadRequest先。IOException:进程无法访问该文件"C: ' FileStore ' G98 ' E16884 ' R6507679 ' JpegBackup022620132102384484.zip"因为它正在被其他进程使用。
你不能,基本上-你必须尝试打开文件进行写入,如果你得到一个异常,你不能写入它:(
即使你可以先做一个单独的检查,结果也会在你开始写之前过期——你以后仍然可能以异常结束。
你可以试试这样做:
public class FileManager
{
private string _fileName;
private int _numberOfTries;
private int _timeIntervalBetweenTries;
private FileStream GetStream(FileAccess fileAccess)
{
var tries = 0;
while (true)
{
try
{
return File.Open(_fileName, FileMode.Open, fileAccess, Fileshare.None);
}
catch (IOException e)
{
if (!IsFileLocked(e))
throw;
if (++tries > _numberOfTries)
throw new MyCustomException("The file is locked too long: " + e.Message, e);
Thread.Sleep(_timeIntervalBetweenTries);
}
}
}
private static bool IsFileLocked(IOException exception)
{
int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1);
return errorCode == 32 || errorCode == 33;
}
// other code
}
这是我在我的代码中使用的,以克服这样的问题。
攻击的一种方法是每n秒重试一次操作(指定重试的最大次数)。
我认为在试图访问文件之前,没有任何方法可以检查服务器上的进程是否正在使用文件。你可以做的是专门捕获400错误,检查错误消息是否"被另一个进程使用",然后在重试之前短暂休眠。
try
{
int retrysLeft = 10;
while (retrysLeft >= 0)
{
try
{
// attempt to download
retrysLeft = -1;
}
catch (WebException ex)
{
if (ex.InnerException.Message.Contains("used by another process"))
{
retrysLeft--;
Thread.Sleep(1000);
}
else throw;
}
}
}
catch (Exception ex)
{
// Regular error handling
}