/// <summary> /// Fired by CompareService when data transfer is complete and actual comparison starts. We use /// this to update the user on the status of operation. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void CompareService_OnComparisonStarted(object sender, EventArgs e) { UploadInfo uploadInfo = Session["UploadInfo"] as UploadInfo; if (uploadInfo == null) { return; } uploadInfo.IsReady = true; uploadInfo.PercentComplete = 75; uploadInfo.Message = "Chunking complete. Comparison started ..."; }
public static object GetUploadStatus() { UploadInfo info = HttpContext.Current.Session["UploadInfo"] as UploadInfo; if (info == null || !info.IsReady) { // not ready yet ... return(null); } int percentComplete; string message; string pairInfo = info.PairInfo; if (info.UsePercentComplete == true) { percentComplete = info.PercentComplete; message = info.Message; } else { // Get the length of the file and divide that by the total length int soFar = info.UploadedLength; int total = info.ContentLength; if (total == 0) { percentComplete = 0; } else { percentComplete = (int)Math.Ceiling((double)soFar / (double)total * 100); } message = string.Format("Uploading {0} ... {1} of {2} Bytes", info.FileName, soFar, total); } // return the percentage return(new { percentComplete = percentComplete, message = message, pairInfo = pairInfo }); }
/// <summary> /// Fired by CompareService after sending each chunk of data. We use this event to calculate the /// progress of data transfer to the Compare Service. It is only for data transfer purposes. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void CompareService_OnDataSent(object sender, DataSentArgs e) { UploadInfo uploadInfo = Session["UploadInfo"] as UploadInfo; if (uploadInfo == null) { return; } uploadInfo.IsReady = true; long soFar = e.BytesSent; long total = e.BytesTotal; int percentComplete = 0; if (total > 0) { percentComplete = (int)Math.Ceiling((double)soFar / total * 100); } uploadInfo.PercentComplete = percentComplete; string msg = "Chunking {0} - Number of bytes sent: {1} Bytes"; if (e.IsOriginalFile) { msg = string.Format(msg, "Original file [ {0} ]", e.BytesSent); msg = string.Format(msg, _originalFileName); } else { msg = string.Format(msg, "Modified file [ {0} ]", e.BytesSent); msg = string.Format(msg, _modifiedFileName); } uploadInfo.Message = msg; }
/// <summary> /// Actually calls into Control.dll to perform comparison. This call fires DataSent event and /// ComparisonStarted event. We need to set the client credentials for the call before it's executed. /// </summary> /// <param name="originalFile"></param> /// <param name="modifiedFile"></param> /// <param name="optionSet"></param> /// <param name="responseOptions"></param> /// <param name="uploadInfo"></param> /// <returns></returns> private CompareResults DoComparison(HttpPostedFile originalPostedFile, HttpPostedFile modifiedPostedFile, string optionSet, ResponseOptions responseOptions, ref UploadInfo uploadInfo) { ICompareService compareService = CreateAppropriateService(); compareService.ComparisonStarted += new EventHandler(CompareService_OnComparisonStarted); compareService.DataSent += new EventHandler <DataSentArgs>(CompareService_OnDataSent); uploadInfo.IsReady = true; uploadInfo.PercentComplete = 10; uploadInfo.Message = "Authenticating request ..."; string username = (string)Session["UserName"]; string domain = (string)Session["Domain"]; string password = (string)Session["Passw"]; password = CodePassword(password); compareService.SetClientCredentials(username, password, domain); string serviceVersion; string compositorVersion; if (!compareService.VerifyConnection(out serviceVersion, out compositorVersion)) { uploadInfo.IsReady = false; return(null); } uploadInfo.PercentComplete = 15; uploadInfo.Message = "Authentication was successful ... reading files"; uploadInfo.PercentComplete = 20; uploadInfo.Message = "Chunking files ..."; compareService.CompareOptions = optionSet; compareService.ComparisonOutput = responseOptions; compareService.UseChunking = true; compareService.ChunkSize = _chunkSize; var originalFile = originalPostedFile.InputStream; var modifiedFile = modifiedPostedFile.InputStream; originalFile.Seek(0, SeekOrigin.Begin); modifiedFile.Seek(0, SeekOrigin.Begin); // As _lastModifiedFileIndex is zero-based, so increment it befor displaying uploadInfo.PairInfo = "Comparing File Pair " + (_lastModifiedFileIndex + 1).ToString(); CompareResults results = compareService.CompareEx(originalFile, modifiedFile, CreateDocumentInfo(originalPostedFile.FileName), CreateDocumentInfo(modifiedPostedFile.FileName)); uploadInfo.PercentComplete = 100; uploadInfo.Message = "Comparison completed ..."; uploadInfo.IsReady = false; return(results); }
/// <summary> /// Saves the file to web-server disk. Saves Original file on the root of session-based path, /// whereas we create an index-based subdirectory for each modified file and its resultant files, e.g. /// session-based-path/0 for first modified file and session-based-path/1 for second and so on. /// </summary> /// <param name="postedFile"></param> /// <param name="originalFile"></param> /// <param name="uploadInfo"></param> /// <returns></returns> private string ProcessFile(HttpPostedFile postedFile, bool originalFile, ref UploadInfo uploadInfo) { // Do some basic validation if (postedFile == null || postedFile.ContentLength == 0) { ShowMessage(GenerateScriptID("progress"), "error", "There was a problem with the file."); uploadInfo.IsReady = false; return(string.Empty); } string virtualFilePath = string.Empty; // build the local path if (originalFile) { virtualFilePath = Path.Combine(_sessionBasePath, Path.GetFileName(postedFile.FileName)); } else { virtualFilePath = Path.Combine(_sessionBasePath, _lastModifiedFileIndex.ToString()); virtualFilePath = Path.Combine(virtualFilePath, Path.GetFileName(postedFile.FileName)); } virtualFilePath = virtualFilePath.Replace('\\', '/'); string filepath = Server.MapPath(virtualFilePath); // build the structure and stuff it into session uploadInfo.ContentLength = postedFile.ContentLength; uploadInfo.FileName = Path.GetFileName(filepath); uploadInfo.UploadedLength = 0; // Let the polling process know that we are done initializing ... uploadInfo.IsReady = true; int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; string directoryPath = Path.GetDirectoryName(filepath); if (!Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } if (File.Exists(filepath)) { File.Delete(filepath); } // Write the bytes to disk using (FileStream fs = new FileStream(filepath, FileMode.Create)) { // As long as we haven't written everything ... while (uploadInfo.UploadedLength < uploadInfo.ContentLength) { // Fill the buffer from the input stream int bytes = postedFile.InputStream.Read(buffer, 0, bufferSize); // Write the bytes to the file stream fs.Write(buffer, 0, bytes); // Update the number the webservice is polling on uploadInfo.UploadedLength += bytes; // Its not a good idea to move Flush in the loop but in case of very large files, // if Flush-ing is deffered untill end, it occupies a lot of memory, and takes quite // long to Flush-out the complete buffer, hence giving an un-explainable delay when the // progress bar is showing 100%. So user is unable to understand whats taking so long. // So we keep on flushing. This will cause frequent H/D hits, and can increase the overall // time, but will give a comparatively better user-experience. fs.Flush(); } } // Let the parent page know we have processed the upload string message = "{0} has been uploaded successfully."; message = string.Format(message, Path.GetFileName(filepath)); ShowMessage(GenerateScriptID("progress"), "success", message); uploadInfo.IsReady = false; return(virtualFilePath); }
/// <summary> /// Makes calls to process files and do Comparison. /// The files are placed in Files collection in the order of appearance on the HTML form. /// First of all Original file is saved. Then for each modified file, file is saved and compared /// against the original file. Modified files can be more than one. /// </summary> private void ProcessFilesAndDoComparison() { UploadInfo uploadInfo = null; try { // Validate the data. if (!IsDataValid()) { UpdatePageUI(); return; } // Upload object used by Default.aspx to report progress to the user uploadInfo = Session["UploadInfo"] as UploadInfo; uploadInfo.IsReady = false; uploadInfo.UsePercentComplete = false; // Read output format ResponseOptions responseOptions = (ResponseOptions)Enum.Parse(typeof(ResponseOptions), ResponseOptionsDropDownList.SelectedValue); // Read rendering set from file string renderingSet = RenderingSetDropDownList.SelectedValue; string optionSet = File.ReadAllText(Request.MapPath(Path.Combine(_renderSetPath, renderingSet))); string originalFileVirtualPath = string.Empty; double originalFileSizeInKB = 0; _resultantFiles.Clear(); // Process original file first. HttpPostedFile originalPostedFile = Request.Files["OriginalFile"]; if (originalPostedFile != null) { originalFileVirtualPath = ProcessFile(originalPostedFile, true, ref uploadInfo); _originalFileName = Path.GetFileName(originalFileVirtualPath); originalFileSizeInKB = (double)originalPostedFile.ContentLength / 1024; } foreach (string postedFile in Request.Files.Keys) { if (postedFile == "OriginalFile") { // We have already had it. continue; } // Now the modified ones. HttpPostedFile modifiedPostedFile = Request.Files[postedFile]; if (modifiedPostedFile.ContentLength <= 0) { continue; } string modifiedFileVirtualPath = ProcessFile(modifiedPostedFile, false, ref uploadInfo); _modifiedFileName = Path.GetFileName(modifiedFileVirtualPath); double modifiedFileSizeInKB = (double)modifiedPostedFile.ContentLength / 1024; // Update progress uploadInfo.IsReady = true; uploadInfo.UsePercentComplete = true; uploadInfo.PercentComplete = 3; uploadInfo.Message = "Starting comparison ..."; // Perform comparison CompareResults results = DoComparison(originalPostedFile, modifiedPostedFile, optionSet, responseOptions, ref uploadInfo); if (results != null) { ShowMessage(GenerateScriptID("comp"), "success", " Comparison completed successfully. Displaying results."); // We save results for each modified file during the process, and sum up these // intermediate results after we are done with comparing all the modified files // provided by user. HandleIntermediateResults(results, responseOptions, modifiedFileVirtualPath, modifiedFileSizeInKB); _lastModifiedFileIndex++; ShowMessage(GenerateScriptID("comp"), "success", " Comparison completed successfully."); } else { ShowMessage(GenerateScriptID("comp"), "error", " Comparison failed. One possible reason is failure of document format conversion."); } } // Prepare final result structs ComparisonResult comparisonResult = HandleFinalResults(originalFileVirtualPath, originalFileSizeInKB, renderingSet); // Show the results. DisplayResults(comparisonResult); } catch (System.Security.SecurityException ex) { if (uploadInfo != null) { uploadInfo.IsReady = false; } string message = " Credentials provided are either empty or invalid. " + ex.Message; ShowMessage(GenerateScriptID("comp"), "error", message); ToggleUploadButtonAndStatusPane(true); } catch (System.ServiceModel.EndpointNotFoundException ex) { if (uploadInfo != null) { uploadInfo.IsReady = false; } string message = " Either Compare Service is not running or host/port address is invalid. " + ex.Message; ShowMessage(GenerateScriptID("comp"), "error", message); ToggleUploadButtonAndStatusPane(true); } catch (TimeoutException ex) { if (uploadInfo != null) { uploadInfo.IsReady = false; } string message = " The connection between server and client is lost because of a timeout. " + ex.Message; ShowMessage(GenerateScriptID("comp"), "error", message); ToggleUploadButtonAndStatusPane(true); } catch (InvalidDataException ex) { if (uploadInfo != null) { uploadInfo.IsReady = false; } string message = " There was an error processing the data. This might be because a document could not be converted. " + ex.Message; ShowMessage(GenerateScriptID("comp"), "error", message); ToggleUploadButtonAndStatusPane(true); } catch (System.ServiceModel.ServerTooBusyException ex) { if (uploadInfo != null) { uploadInfo.IsReady = false; } string message = " Too many simultaneous requests. Try again after a while. " + ex.Message; ShowMessage(GenerateScriptID("comp"), "error", message); ToggleUploadButtonAndStatusPane(true); } catch (System.ServiceModel.FaultException <string> ex) { if (uploadInfo != null) { uploadInfo.IsReady = false; } string message = " An error occurred while comparing documents. " + ex.Detail; ShowMessage(GenerateScriptID("comp"), "error", message); ToggleUploadButtonAndStatusPane(true); } catch (Exception ex) { if (uploadInfo != null) { uploadInfo.IsReady = false; } string message = " An error occurred while comparing documents. " + ex.Message; ShowMessage(GenerateScriptID("comp"), "error", message); ToggleUploadButtonAndStatusPane(true); } }