protected virtual void CloseStreams() { if (ReadStream != null) { ReadStream.Close(); } if (WriteStream != null) { WriteStream.Close(); } }
public void Clear() { WriteStream.Close(); HStream.Close(); File.Delete(HPath); HStream = new FileStream(HPath, FileMode.OpenOrCreate, FileAccess.ReadWrite); ReadOffset = 0; WriteStream = new StreamWriter(HStream, Encoding.UTF8, 256, true); HBuffer.Clear(); }
public void OpenStream() { if (WriteStream != null) { WriteStream.Flush(); WriteStream.Close(); WriteStream.Dispose(); WriteStream = null; } WriteStream = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None); TimeStarted = Environment.TickCount; }
public void OpenStream() { if (WriteStream != null) { WriteStream.Flush(); WriteStream.Close(); WriteStream.Dispose(); WriteStream = null; } WriteStream = File.Open(FilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write); TimeStarted = Environment.TickCount; }
public override void Close() { if (!leaveOpen) { try { WriteStream.Close(); } finally { ReadStream.Close(); } } }
public virtual void Close() { ActionUtils.IgnoreExceptions(Flush); ActionUtils.IgnoreExceptions(() => WriteStream.Close()); ActionUtils.IgnoreExceptions(() => Socket.Close()); if (!closeFired) { closeFired = true; OnClosed(EventArgs.Empty); } }
protected virtual void Dispose(bool disposing) { if (disposed) { return; } if (disposing) { if (WriteStream != null) { WriteStream.Flush(); WriteStream.Close(); WriteStream.Dispose(); WriteStream = null; } } disposed = true; }
protected override void Dispose(bool disposing) { if (disposing) { closedCancelSource.Cancel(); if (!leaveOpen) { if (WriteStream != null) { WriteStream.Close(); } if (ReadStream != null) { ReadStream.Close(); } } } base.Dispose(disposing); }
public async Task CloseAsync(CancellationToken cancel_token) { if (!closedCancelSource.IsCancellationRequested) { writeBuffer.CloseWrite(); readBuffer.CloseRead(); try { await Task.WhenAll(writeTask, readTask).ConfigureAwait(false); } catch (Exception) { } closedCancelSource.Cancel(); if (WriteStream != null) { WriteStream.Close(); } if (ReadStream != null) { ReadStream.Close(); } } Close(); }
protected override void Dispose(bool disposing) { if (disposing && !closedCancelSource.IsCancellationRequested) { writeBuffer.CloseWrite(); readBuffer.CloseRead(); try { Task.WhenAll(writeTask, readTask).Wait(); } catch (AggregateException) { } closedCancelSource.Cancel(); if (WriteStream != null) { WriteStream.Close(); } if (ReadStream != null) { ReadStream.Close(); } closedCancelSource.Dispose(); } base.Dispose(disposing); }
/// <summary> /// Saves the Zip archive to a file, specified by the Name property of the /// <c>ZipFile</c>. /// </summary> /// /// <remarks> /// <para> /// The <c>ZipFile</c> instance is written to storage, typically a zip file /// in a filesystem, only when the caller calls <c>Save</c>. In the typical /// case, the Save operation writes the zip content to a temporary file, and /// then renames the temporary file to the desired name. If necessary, this /// method will delete a pre-existing file before the rename. /// </para> /// /// <para> /// The <see cref="ZipFile.Name"/> property is specified either explicitly, /// or implicitly using one of the parameterized ZipFile constructors. For /// COM Automation clients, the <c>Name</c> property must be set explicitly, /// because COM Automation clients cannot call parameterized constructors. /// </para> /// /// <para> /// When using a filesystem file for the Zip output, it is possible to call /// <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each /// call the zip content is re-written to the same output file. /// </para> /// /// <para> /// Data for entries that have been added to the <c>ZipFile</c> instance is /// written to the output when the <c>Save</c> method is called. This means /// that the input streams for those entries must be available at the time /// the application calls <c>Save</c>. If, for example, the application /// adds entries with <c>AddEntry</c> using a dynamically-allocated /// <c>MemoryStream</c>, the memory stream must not have been disposed /// before the call to <c>Save</c>. See the <see /// cref="ZipEntry.InputStream"/> property for more discussion of the /// availability requirements of the input stream for an entry, and an /// approach for providing just-in-time stream lifecycle management. /// </para> /// /// </remarks> /// /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/> /// /// <exception cref="Ionic.Zip.BadStateException"> /// Thrown if you haven't specified a location or stream for saving the zip, /// either in the constructor or by setting the Name property, or if you try /// to save a regular zip archive to a filename with a .exe extension. /// </exception> /// /// <exception cref="System.OverflowException"> /// Thrown if <see cref="MaxOutputSegmentSize"/> is non-zero, and the number /// of segments that would be generated for the spanned zip file during the /// save operation exceeds 99. If this happens, you need to increase the /// segment size. /// </exception> /// public void Save() { try { bool thisSaveUsedZip64 = false; _saveOperationCanceled = false; _numberOfSegmentsForMostRecentSave = 0; OnSaveStarted(); if (WriteStream == null) { throw new BadStateException("You haven't specified where to save the zip."); } if (_name != null && _name.EndsWith(".exe") && !_SavingSfx) { throw new BadStateException("You specified an EXE for a plain zip file."); } // check if modified, before saving. if (!_contentsChanged) { OnSaveCompleted(); if (Verbose) { StatusMessageTextWriter.WriteLine("No save is necessary...."); } return; } Reset(true); if (Verbose) { StatusMessageTextWriter.WriteLine("saving...."); } // validate the number of entries if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never) { throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance."); } // write an entry in the zip for each file int n = 0; // workitem 9831 ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries; foreach (ZipEntry e in c) // _entries.Values { OnSaveEntry(n, e, true); e.Write(WriteStream); if (_saveOperationCanceled) { break; } n++; OnSaveEntry(n, e, false); if (_saveOperationCanceled) { break; } // Some entries can be skipped during the save. if (e.IncludedInMostRecentSave) { thisSaveUsedZip64 |= e.OutputUsedZip64.Value; } } if (_saveOperationCanceled) { return; } var zss = WriteStream as ZipSegmentedStream; _numberOfSegmentsForMostRecentSave = (zss != null) ? zss.CurrentSegment : 1; bool directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure (WriteStream, c, _numberOfSegmentsForMostRecentSave, _zip64, Comment, new ZipContainer(this)); OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive); _hasBeenSaved = true; _contentsChanged = false; thisSaveUsedZip64 |= directoryNeededZip64; _OutputUsesZip64 = new Nullable <bool>(thisSaveUsedZip64); if (_fileAlreadyExists && this._readstream != null) { // This means we opened and read a zip file. // If we are now saving, we need to close the orig file, first. this._readstream.Close(); this._readstream = null; } // the archiveStream for each entry needs to be null foreach (var e in c) { var zss1 = e._archiveStream as ZipSegmentedStream; if (zss1 != null) #if NETCF { zss1.Close(); } #else { zss1.Dispose(); } #endif e._archiveStream = null; } // do the rename as necessary if (_name != null && (_temporaryFileName != null || zss != null)) { // _temporaryFileName may remain null if we are writing to a stream. // only close the stream if there is a file behind it. #if NETCF WriteStream.Close(); #else WriteStream.Dispose(); #endif if (_saveOperationCanceled) { return; } string tmpName = null; if (File.Exists(_name)) { // the steps: // // 1. Delete tmpName // 2. move existing zip to tmpName // 3. rename (File.Move) working file to name of existing zip // 4. delete tmpName // // This series of steps avoids the exception, // System.IO.IOException: // "Cannot create a file when that file already exists." // // Cannot just call File.Replace() here because // there is a possibility that the TEMP volume is different // that the volume for the final file (c:\ vs d:\). // So we need to do a Delete+Move pair. // // But, when doing the delete, Windows allows a process to // delete the file, even though it is held open by, say, a // virus scanner. It gets internally marked as "delete // pending". The file does not actually get removed from the // file system, it is still there after the File.Delete // call. // // Therefore, we need to move the existing zip, which may be // held open, to some other name. Then rename our working // file to the desired name, then delete (possibly delete // pending) the "other name". // // Ideally this would be transactional. It's possible that the // delete succeeds and the move fails. Lacking transactions, if // this kind of failure happens, we're hosed, and this logic will // throw on the next File.Move(). // //File.Delete(_name); // workitem 10447 #if NETCF || SILVERLIGHT tmpName = _name + "." + SharedUtilities.GenerateRandomStringImpl(8, 0) + ".tmp"; #else tmpName = _name + "." + Path.GetRandomFileName(); #endif if (File.Exists(tmpName)) { DeleteFileWithRetry(tmpName); } File.Move(_name, tmpName); } OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive); File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName, _name); OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive); if (tmpName != null) { try { // not critical if (File.Exists(tmpName)) { File.Delete(tmpName); } } catch { // don't care about exceptions here. } } _fileAlreadyExists = true; } _readName = _name; NotifyEntriesSaveComplete(c); OnSaveCompleted(); _JustSaved = true; } // workitem 5043 finally { CleanupAfterSaveOperation(); } return; }
/// <summary> /// Saves the Zip archive to a file, specified by the Name property of the <c>ZipFile</c>. /// </summary> /// /// <remarks> /// <para> /// The <c>ZipFile</c> instance is written to storage, typically a zip file in a /// filesystem, only when the caller calls <c>Save</c>. The Save operation writes /// the zip content to a temporary file, and then renames the temporary file /// to the desired name. If necessary, this method will delete a pre-existing file /// before the rename. /// </para> /// /// <para> The <see cref="ZipFile.Name"/> property is specified either /// explicitly, or implicitly using one of the parameterized ZipFile /// constructors. For COM Automation clients, the <c>Name</c> property must be /// set explicitly, because COM Automation clients cannot call parameterized /// constructors. </para> /// /// <para> /// When using a filesystem file for the Zip output, it is possible to call /// <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each call the zip /// content is re-written to the same output file. /// </para> /// /// <para> /// Data for entries that have been added to the <c>ZipFile</c> instance is written /// to the output when the <c>Save</c> method is called. This means that the input /// streams for those entries must be available at the time the application calls /// <c>Save</c>. If, for example, the application adds entries with <c>AddEntry</c> /// using a dynamically-allocated <c>MemoryStream</c>, the memory stream must not /// have been disposed before the call to <c>Save</c>. See the <see /// cref="ZipEntry.InputStream"/> property for more discussion of the availability /// requirements of the input stream for an entry, and an approach for providing /// just-in-time stream lifecycle management. /// </para> /// /// </remarks> /// /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/> /// /// <exception cref="Ionic.Zip.BadStateException"> /// Thrown if you haven't specified a location or stream for saving the zip, /// either in the constructor or by setting the Name property, or if you try to /// save a regular zip archive to a filename with a .exe extension. /// </exception> /// public void Save() { try { bool thisSaveUsedZip64 = false; _saveOperationCanceled = false; _numberOfSegmentsForMostRecentSave = 0; OnSaveStarted(); if (WriteStream == null) { throw new BadStateException("You haven't specified where to save the zip."); } if (_name != null && _name.EndsWith(".exe") && !_SavingSfx) { throw new BadStateException("You specified an EXE for a plain zip file."); } // check if modified, before saving. if (!_contentsChanged) { OnSaveCompleted(); if (Verbose) { StatusMessageTextWriter.WriteLine("No save is necessary...."); } return; } Reset(); if (Verbose) { StatusMessageTextWriter.WriteLine("saving...."); } // validate the number of entries if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never) { throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance."); } // write an entry in the zip for each file int n = 0; // workitem 9831 ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries; foreach (ZipEntry e in c) // _entries.Values { OnSaveEntry(n, e, true); e.Write(WriteStream); if (_saveOperationCanceled) { break; } n++; OnSaveEntry(n, e, false); if (_saveOperationCanceled) { break; } // Some entries can be skipped during the save. if (e.IncludedInMostRecentSave) { thisSaveUsedZip64 |= e.OutputUsedZip64.Value; } } if (_saveOperationCanceled) { return; } var zss = WriteStream as ZipSegmentedStream; _numberOfSegmentsForMostRecentSave = (zss != null) ? zss.CurrentSegment : 1; bool directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure(WriteStream, c, _numberOfSegmentsForMostRecentSave, _zip64, Comment, ProvisionalAlternateEncoding); OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive); _hasBeenSaved = true; _contentsChanged = false; thisSaveUsedZip64 |= directoryNeededZip64; _OutputUsesZip64 = new Nullable <bool>(thisSaveUsedZip64); // do the rename as necessary if (_name != null && (_temporaryFileName != null || zss != null)) { // _temporaryFileName may remain null if we are writing to a stream. // only close the stream if there is a file behind it. WriteStream.Close(); #if !NETCF WriteStream.Dispose(); #endif if (_saveOperationCanceled) { return; } if ((_fileAlreadyExists) && (this._readstream != null)) { // This means we opened and read a zip file. // If we are now saving to the same file, we need to close the // orig file, first. this._readstream.Close(); this._readstream = null; // the archiveStream for each entry needs to be null foreach (var e in c) { e._archiveStream = null; } } if (_fileAlreadyExists) { // We do not just call File.Replace() here because // there is a possibility that the TEMP volume is different // that the volume for the final file (c:\ vs d:\). // So we need to do a Delete+Move pair. // // Ideally this would be transactional. // // It's possible that the delete succeeds and the move fails. // in that case, we're hosed, and we'll throw. // // Could make this more complicated by moving (renaming) the first file, then // moving the second, then deleting the first file. But the // error handling and unwrap logic just gets more complicated. // // Better to just keep it simple. File.Delete(_name); } OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive); File.Move((zss != null) ? zss.CurrentName : _temporaryFileName, _name); OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive); _fileAlreadyExists = true; } NotifyEntriesSaveComplete(c); OnSaveCompleted(); _JustSaved = true; } // workitem 5043 finally { CleanupAfterSaveOperation(); } return; }
/// <summary> /// Saves the Zip archive to a file, specified by the Name property of the /// <c>ZipFile</c>. /// </summary> /// /// <remarks> /// <para> /// The <c>ZipFile</c> instance is written to storage, typically a zip file /// in a filesystem, only when the caller calls <c>Save</c>. In the typical /// case, the Save operation writes the zip content to a temporary file, and /// then renames the temporary file to the desired name. If necessary, this /// method will delete a pre-existing file before the rename. /// </para> /// /// <para> /// The <see cref="ZipFile.Name"/> property is specified either explicitly, /// or implicitly using one of the parameterized ZipFile constructors. For /// COM Automation clients, the <c>Name</c> property must be set explicitly, /// because COM Automation clients cannot call parameterized constructors. /// </para> /// /// <para> /// When using a filesystem file for the Zip output, it is possible to call /// <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each /// call the zip content is re-written to the same output file. /// </para> /// /// <para> /// Data for entries that have been added to the <c>ZipFile</c> instance is /// written to the output when the <c>Save</c> method is called. This means /// that the input streams for those entries must be available at the time /// the application calls <c>Save</c>. If, for example, the application /// adds entries with <c>AddEntry</c> using a dynamically-allocated /// <c>MemoryStream</c>, the memory stream must not have been disposed /// before the call to <c>Save</c>. See the <see /// cref="ZipEntry.InputStream"/> property for more discussion of the /// availability requirements of the input stream for an entry, and an /// approach for providing just-in-time stream lifecycle management. /// </para> /// /// </remarks> /// /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/> /// /// <exception cref="Ionic.Zip.BadStateException"> /// Thrown if you haven't specified a location or stream for saving the zip, /// either in the constructor or by setting the Name property, or if you try /// to save a regular zip archive to a filename with a .exe extension. /// </exception> /// /// <exception cref="System.OverflowException"> /// Thrown if <see cref="MaxOutputSegmentSize"/> is non-zero, and the number /// of segments that would be generated for the spanned zip file during the /// save operation exceeds 99. If this happens, you need to increase the /// segment size. /// </exception> /// public void Save() { try { bool thisSaveUsedZip64 = false; _saveOperationCanceled = false; _numberOfSegmentsForMostRecentSave = 0; OnSaveStarted(); if (WriteStream == null) { throw new BadStateException("You haven't specified where to save the zip."); } if (_name != null && _name.EndsWith(".exe") && !_SavingSfx) { throw new BadStateException("You specified an EXE for a plain zip file."); } // check if modified, before saving. if (!_contentsChanged) { OnSaveCompleted(); if (Verbose) { StatusMessageTextWriter.WriteLine("No save is necessary...."); } return; } Reset(true); if (Verbose) { StatusMessageTextWriter.WriteLine("saving...."); } // validate the number of entries if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never) { throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance."); } // write an entry in the zip for each file int n = 0; // workitem 9831 ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries; foreach (ZipEntry e in c) // _entries.Values { OnSaveEntry(n, e, true); e.Write(WriteStream); if (_saveOperationCanceled) { break; } n++; OnSaveEntry(n, e, false); if (_saveOperationCanceled) { break; } // Some entries can be skipped during the save. if (e.IncludedInMostRecentSave) { thisSaveUsedZip64 |= e.OutputUsedZip64.Value; } } if (_saveOperationCanceled) { return; } var zss = WriteStream as ZipSegmentedStream; _numberOfSegmentsForMostRecentSave = (zss != null) ? zss.CurrentSegment : 1; bool directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure (WriteStream, c, _numberOfSegmentsForMostRecentSave, _zip64, Comment, new ZipContainer(this)); OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive); _hasBeenSaved = true; _contentsChanged = false; thisSaveUsedZip64 |= directoryNeededZip64; _OutputUsesZip64 = new Nullable <bool>(thisSaveUsedZip64); // do the rename as necessary if (_name != null && (_temporaryFileName != null || zss != null)) { // _temporaryFileName may remain null if we are writing to a stream. // only close the stream if there is a file behind it. #if NETCF WriteStream.Close(); #else WriteStream.Dispose(); #endif if (_saveOperationCanceled) { return; } if (_fileAlreadyExists && this._readstream != null) { // This means we opened and read a zip file. // If we are now saving to the same file, we need to close the // orig file, first. this._readstream.Close(); this._readstream.Dispose(); this._readstream = null; // the archiveStream for each entry needs to be null foreach (var e in c) { var zss1 = e._archiveStream as ZipSegmentedStream; if (zss1 != null) #if NETCF { zss1.Close(); } #else { zss1.Dispose(); } #endif e._archiveStream = null; } } if (_fileAlreadyExists && this._writestream != null) { this.WriteStream.Close(); } string tmpName = null; if (File.Exists(_name)) { // the steps: // // 1. Delete tmpName // 2. move existing zip to tmpName // 3. rename (File.Move) working file to name of existing zip // 4. delete tmpName // // This series of steps avoids the exception, // System.IO.IOException: // "Cannot create a file when that file already exists." // // Cannot just call File.Replace() here because // there is a possibility that the TEMP volume is different // that the volume for the final file (c:\ vs d:\). // So we need to do a Delete+Move pair. // // But, when doing the delete, Windows allows a process to // delete the file, even though it is held open by, say, a // virus scanner. It gets internally marked as "delete // pending". The file does not actually get removed from the // file system, it is still there after the File.Delete // call. // // Therefore, we need to move the existing zip, which may be // held open, to some other name. Then rename our working // file to the desired name, then delete (possibly delete // pending) the "other name". // // Ideally this would be transactional. It's possible that the // delete succeeds and the move fails. Lacking transactions, if // this kind of failure happens, we're hosed, and this logic will // throw on the next File.Move(). // //File.Delete(_name); // workitem 10447 #if NETCF || SILVERLIGHT tmpName = _name + "." + SharedUtilities.GenerateRandomStringImpl(8, 0) + ".tmp"; #else tmpName = _name + "." + Path.GetRandomFileName(); #endif if (File.Exists(tmpName)) { DeleteFileWithRetry(tmpName); } try { File.Move(_name, tmpName); } catch { if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Break(); //Look at the comment below. Added this to force a break here instead of your catch so you don't miss the cause and waste your time like I did } throw; } //Oh boy. You've just hit an exception on that File.Move line right above this stating that the template file can't be renamed because it's open //in another process, right? //Congratulation! You've probably run into the same gibberish I ran into! //Check to make sure your file streams are closed, and ITpipes/Template Editor/Winrar/7-Zip don't have the template file open. I'm betting you won't find anything. //If you try closing Visual Studio and running the binary directly I'm betting you won't have this crash occur. Go ahead--try it. //What the hell, right? //The XAML designer process (XDesProc.exe) is configured, by default, to populate its ViewModel in the designer UI. This creates a copy of the model--which creates a second //Ionic.Zip.ZipFile object using the same template file. So when *this* ZipFile object attempts to move the existing template to replace it with an updated file //the exception is thrown. //To fix this, disable the following option in the Visual Studio toolbar above: // Tools -> Options -> XAML Designer -> "Run project code in XAML Designer (if supported)" //Once that's disabled, restart Visual Studio. Problem solved. //Hopefully these comments will prevent someone else from wasting their time obsessing over their streams and AntiVirus. - Vincent Nary } OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive); File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName, _name); OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive); if (tmpName != null) { try { // not critical if (File.Exists(tmpName)) { File.Delete(tmpName); } } catch { // don't care about exceptions here. } } _fileAlreadyExists = true; } NotifyEntriesSaveComplete(c); OnSaveCompleted(); _JustSaved = true; } // workitem 5043 finally { CleanupAfterSaveOperation(); } return; }
byte[] ReadBuffer = new byte[1024 * 128 * 1]; // кеш - 0.5 Мб void DownloadFileStreamly(Stream dataStream) { DownloadProgress CurrentDownloadProgress = new DownloadProgress(); Stream WriteStream = null; Exception TempEx = null; try { if (Current.DownloadPathSave != null) { string FilePath = Current.DownloadPathSave + "\\" + Current.Filename; if (System.IO.File.Exists(FilePath)) { System.IO.FileInfo xx = new System.IO.FileInfo(FilePath); if (xx.Length > Current.FileSize) { xx.Delete(); Current.BytesDownloaded = 0; } } else { Current.BytesDownloaded = 0; } WriteStream = new FileStream(FilePath, FileMode.OpenOrCreate); CurrentDownloadProgress.FilePath = FilePath; } else { WriteStream = Current.OutputData; } if (Current.FileSize == Current.BytesDownloaded && Current.BytesDownloaded != 0 && Current.FileDownloaded) { throw new Exception("Файл уже закачан " + Current.FullURL); } if (Current.FileSize > 0 && Current.BytesDownloaded == 0 && WriteStream.Length != Current.FileSize) { // если известен размер файла и файл только что добавили, то создаем пустышку в размер файла WriteStream.SetLength(Current.FileSize); } if (WriteStream.Length == Current.BytesDownloaded && WriteStream.Length != 0) { Current.BytesDownloaded = 0; } WriteStream.Position = Current.BytesDownloaded; DateTime BeginTime = DateTime.Now; TimeSpan TimeDifference; TimeSpan RemainTime; int BeginDownloadBytes = Current.BytesDownloaded; int ReadData = 1; int BufferOffset = 0; double LastTimeDifferenceSeconds = 0; while (DownloadFileThreadRunning) { if (!DownloadFileThreadPause) { // если не была задана пауза ReadData = dataStream.Read(ReadBuffer, BufferOffset, ReadBuffer.Length - BufferOffset); BufferOffset += ReadData; TimeDifference = DateTime.Now - BeginTime; if (((ReadBuffer.Length - BufferOffset) < 1024) || // осталось черезчур мало места в буффере (ReadData == 0) || // закачка закончилась (TimeDifference.TotalSeconds != LastTimeDifferenceSeconds)) // но не реже 1 раза в секунду { WriteStream.Write(ReadBuffer, 0, BufferOffset); Current.BytesDownloaded += BufferOffset; if (TimeDifference.TotalSeconds != LastTimeDifferenceSeconds) { CurrentDownloadProgress.DownloadSize = Math.Max(Current.BytesDownloaded, Current.FileSize); CurrentDownloadProgress.Bytes = Current.BytesDownloaded; CurrentDownloadProgress.Speed = ( (Current.BytesDownloaded - BeginDownloadBytes) * 1000.0f / (float)TimeDifference.TotalMilliseconds); RemainTime = new TimeSpan((long) ((TimeDifference.Ticks * (Current.FileSize - Current.BytesDownloaded)) / (float)(Current.BytesDownloaded - BeginDownloadBytes)) ); CurrentDownloadProgress.RemainTime = RemainTime.ToString(); CurrentDownloadProgress.Type = DownloadMessageType.DownloadProgressShow; SygnalEventProgress(CurrentDownloadProgress); if (TimeDifference.TotalSeconds >= 5) { BeginTime = DateTime.Now; BeginDownloadBytes = Current.BytesDownloaded; } } ; BufferOffset = 0; LastTimeDifferenceSeconds = TimeDifference.TotalSeconds; } } else {// была задана пауза CurrentDownloadProgress.Type = DownloadMessageType.DownloadPaused; SygnalEventProgress(CurrentDownloadProgress); Thread.Sleep(500); } if (ReadData == 0) { // все закачали if (Current.FileSize == -1) { // не был известен размер файла Current.FileSize = Current.BytesDownloaded; } break; } } } catch (Exception ex) { TempEx = ex; // ErrorWork(new Exception("Размер файла " + Current.FileSize)); } finally { WriteStream.Close(); // финальное состояние CurrentDownloadProgress.DownloadSize = Math.Max(Current.BytesDownloaded, Current.FileSize); CurrentDownloadProgress.Bytes = Current.BytesDownloaded; CurrentDownloadProgress.Type = DownloadMessageType.DownloadProgressShow; SygnalEventProgress(CurrentDownloadProgress); if (DownloadFileThreadRunning && Current.FileSize == Current.BytesDownloaded) { // файл закончен CurrentDownloadProgress.Type = DownloadMessageType.DownloadFinished; SygnalEventProgress(CurrentDownloadProgress); Current.FileDownloaded = true; } else { // была нажата кнопка стоп -поэтому - ничего не вызываем CurrentDownloadProgress.Type = DownloadMessageType.DownloadStopped; CurrentDownloadProgress.AdditionalInfo = "DownloadFileThreadRunning " + DownloadFileThreadRunning.ToString() + " Current.FileSize = " + Current.FileSize.ToString() + " Current.BytesDownloaded = " + Current.BytesDownloaded.ToString(); SygnalEventProgress(CurrentDownloadProgress); } DownloadFileThreadRunning = false; } if (TempEx != null) { throw TempEx; } }