我被要求爲我工作的組織編寫一個文檔管理系統,它提供了一系列與不同記錄相關的九個不同工作流程。在這些工作流程中,將文檔添加到「文件」或記錄中,並根據業務規則將這些文檔的子集發佈到公共網站。長時間運行文件操作和執行超時
這些文檔幾乎沒有例外的PDF格式,並且任何一個記錄通常少於20個正在處理。
將其作爲Web應用程序構建的主要原因是將文件保存在我們的數據中心和高速交換機上,而不是通過遠程站點上可能較慢的連接速度在位置之間嘗試複製和備份。
該系統完美地工作,直到一個更大的一系列文件(114個PDF文件完全在大小329MB)超時95%左右的的方式。
的代碼是(IncomingDocuments的類型是List <的FileInfo的> ) -
List<string> filesSuccessfullyAdded = new List<string>();
foreach (FileInfo incomingFile in IncomingDocuments)
{
FileOperations.AddDocument(incomingFile, false, ApplicationCode, (targetDirectoryPath.EndsWith(@"\") ? targetDirectoryPath : targetDirectoryPath + @"\"));
FileInfo copiedDocument = new FileInfo(Path.Combine(targetDirectoryPath, incomingFile.Name));
if (copiedDocument.Exists && copiedDocument.Length == incomingFile.Length && copiedDocument.LastWriteTime == incomingFile.LastWriteTime)
{
filesSuccessfullyAdded.Add(copiedDocument.Name);
}
}
if (filesSuccessfullyAdded.Any())
{
SetupConfirmationLiteral.Text += "<p class='info'>The following files have been successfully added to the application file-</p>";
XDocument successfullyAddedList = new XDocument(
new XElement("ul", new XAttribute("class", "documentList")));
foreach (string successfulFile in filesSuccessfullyAdded)
{
successfullyAddedList.Root.Add(new XElement("li", successfulFile));
}
SetupConfirmationLiteral.Text += successfullyAddedList.ToString();
}
var notSuccessfullyAdded = from FileInfo incomingDocument in IncomingDocuments
where !filesSuccessfullyAdded.Contains(incomingDocument.Name)
orderby incomingDocument.Name ascending
select incomingDocument.Name;
if (notSuccessfullyAdded.Any())
{
SetupConfirmationLiteral.Text += "<p class='alert'>The following files have <strong>not</strong> been successfully added to the application file-</p>";
XDocument notAddedList = new XDocument(
new XElement("ul", new XAttribute("class", "documentList")));
foreach (string notAdded in notSuccessfullyAdded)
{
notAddedList.Root.Add(new XElement("li", notAdded));
}
SetupConfirmationLiteral.Text += notAddedList.ToString();
SetupConfirmationLiteral.Text += "<p>A file of the same name may already exist in the target location.</p>";
}
有了一個實用的方法OF-
public static void AddDocument(FileInfo sourceFile, bool appendName, string applicationCode, string targetPath)
{
try
{
DirectoryInfo targetDirectory = new DirectoryInfo(targetPath);
if (targetDirectory.Exists)
{
string targetFileName = (appendName ? sourceFile.Name.Insert(sourceFile.Name.IndexOf(sourceFile.Extension, StringComparison.Ordinal), " UPDATED") : sourceFile.Name);
if (targetDirectory.GetFiles(targetFileName).Any())
{
//Do not throw an exception if the file already exists. Silently return. If the file exists and matches both last modified and size it won't be reported, and can be archived as normal,
//otherwise it should be reported to user in the calling method.
return;
}
string targetFileUnc = Path.Combine(targetPath, targetFileName);
sourceFile.CopyTo(targetFileUnc, overwrite: false);
Logging.FileLogEntry(username: (HttpContext.Current.User.Identity.IsAuthenticated ? HttpContext.Current.User.Identity.Name : "Unknown User"), eventType: LogEventType.AddedDocument,
applicationCode: applicationCode, document: sourceFile.Name, uncPath: targetFileUnc);
}
else
{
throw new PdmsException("Target directory does not exist");
}
}
catch (UnauthorizedAccessException ex)
{
throw new PdmsException("Access was denied to the target directory. Contact the Service Desk.", ex);
}
catch (PathTooLongException)
{
throw new PdmsException(string.Format("Cannot add document {0} to the Site File directory for Application {1} - the combined path is too long. Use the Add Documents workflow to re-add documents to this Site File after renaming {0} to a shorter name.", sourceFile.Name, applicationCode));
}
catch (FileNotFoundException ex)
{
throw new PdmsException("The incoming file was not found. It may have already been added to the application file.", ex);
}
catch (DirectoryNotFoundException ex)
{
throw new PdmsException("The source or the target directory were not found. The document(s) may have already been added to the application file.", ex);
}
catch (IOException ex)
{
throw new PdmsException("Error adding files - file(s) may be locked or there may be server or network problem preventing the copy. Contact the Service Desk.", ex);
}
}
要進行實際的複製和審計。 PdmsException只是一個特定的異常類,我們用它來向用戶顯示有用的錯誤消息,允許他們在可能的情況下解決自己的問題,或者至少給出可以理解的失敗原因。
我知道我可以簡單地增加ExecutionTimeout屬性(http://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.executiontimeout.aspx)超過110秒的默認值 - 最多說300秒 - 這可能意味着在這種情況下超時停止發生,但如果用戶試圖添加或發佈數千個文檔。這種解決方案不能很好地擴展,只是推遲而不是解決問題。
我在Visual Studio 2010中使用.NET 4,據我所知,因此必須使用異步的第三方實現,並等待像AsyncBridge(https://nuget.org/packages/AsyncBridge),如果我們想使用ajax來分組文件和更新進度。我無法訪問Visual Studio 2012或甚至比XP更新的Windows,以便使用Microsoft提供的Async定位包。
鑑於這些限制,是否有辦法對這些文檔進行分組/批處理以避免超時,並且(理想情況下)在每批添加時向用戶提供反饋?如果可以直接實施,我願意探索F#。或者,我應該在這個案例上爲Visual Studio 2012辯護嗎?
我很好奇某事..你的組織可以不使用或實現'SharePoint' ..?聽起來像你被要求重新發明'輪子' – MethodMan 2013-03-26 17:28:25
請問那些誰downvoting問題解釋爲什麼?我非常樂意通過一些推理將它帶入下巴。 – pwdst 2013-03-26 17:30:40
由於我們必須與第三方產品集成,因此Sharepoint不是此方案中的選項。 – pwdst 2013-03-26 17:34:09