/// <summary> /// Ask the user how to handle file collisions /// </summary> /// <param name="p_OutputDir"></param> /// <param name="p_FileName"></param> /// <returns></returns> private bool CanWriteThisFile(string p_OutputDir, string p_ClassName, string p_FileName) { if (File.Exists(p_OutputDir + p_FileName)) { // only ask if they did not check "same for All files" if ((_fhResult & FileHandlingResult.All) == 0) { _FileExists.Invoke(p_OutputDir, p_FileName, ref _fhResult); } // if they said either cancel or skip, tell the caller NOT to write the file if ((_fhResult & FileHandlingResult.Cancel) > 0) { return(false); } else if ((_fhResult & FileHandlingResult.Skip) > 0) { OneTimeFileRequestHandled(); return(false); } else if ((_fhResult & FileHandlingResult.Rename) > 0) { // rename the file // -- find a free extension int i = 0; string ext; do { if (++i > 999) { throw new Exception("Unable to rename file!"); } ext = String.Format(".{0:00#}", i); } while (File.Exists(p_OutputDir + p_ClassName + ext)); // -- finally rename the file File.Move(p_OutputDir + p_FileName, p_OutputDir + p_ClassName + ext); // we handled a one-time request ... OneTimeFileRequestHandled(); } else if ((_fhResult & FileHandlingResult.OverWrite) > 0) { OneTimeFileRequestHandled(); } } // file does not exist, or otherwise safe to write return(true); }
/// <summary> /// Sets output stream for writing unpacked data /// </summary> /// <param name="index">Current file index</param> /// <param name="outStream">Output stream pointer</param> /// <param name="askExtractMode">Extraction mode</param> /// <returns>0 if OK</returns> public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode) { outStream = null; if (Canceled) { return(-1); } _currentIndex = (int)index; if (askExtractMode == AskMode.Extract) { var fileName = _directory; if (!_fileIndex.HasValue) { // Extraction to a file if (_actualIndexes == null || _actualIndexes.Contains(index)) { var data = new PropVariant(); _archive.GetProperty(index, ItemPropId.Path, ref data); var entryName = NativeMethods.SafeCast(data, ""); #region Get entryName if (string.IsNullOrEmpty(entryName)) { if (_filesCount == 1) { var archName = Path.GetFileName(_extractor.FileName); archName = archName.Substring(0, archName.LastIndexOf('.')); if (!archName.EndsWith(".tar", StringComparison.OrdinalIgnoreCase)) { archName += ".tar"; } entryName = archName; } else { entryName = "[no name] " + index.ToString(CultureInfo.InvariantCulture); } } #endregion Get entryName try { fileName = Path.Combine(RemoveIllegalCharacters(_directory, true), RemoveIllegalCharacters(_directoryStructure ? entryName : Path.GetFileName(entryName))); if (string.IsNullOrEmpty(fileName)) { throw new SevenZipArchiveException("Some archive name is null or empty."); } } catch (Exception e) { AddException(e); outStream = _fakeStream; return(0); } _archive.GetProperty(index, ItemPropId.IsDirectory, ref data); if (!NativeMethods.SafeCast(data, false)) { _archive.GetProperty(index, ItemPropId.LastWriteTime, ref data); var time = NativeMethods.SafeCast(data, DateTime.MinValue); if (File.Exists(fileName)) { var fnea = new FileOverwriteEventArgs(fileName); FileExists?.Invoke(this, fnea); if (fnea.Cancel) { Canceled = true; return(-1); } if (string.IsNullOrEmpty(fnea.FileName)) { outStream = _fakeStream; } else { fileName = fnea.FileName; } } _doneRate += 1.0f / _filesCount; var iea = new FileInfoEventArgs(_extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate)); FileExtractionStarted?.Invoke(this, iea); if (iea.Cancel) { Canceled = true; return(-1); } if (iea.Skip) { outStream = _fakeStream; return(0); } CreateDirectory(fileName); try { _fileStream = new OutStreamWrapper(File.Create(fileName), fileName, time, true); } catch (Exception e) { AddException(e is FileNotFoundException ? new IOException($"The file \"{fileName}\" was not extracted due to the File.Create fail.") : e); outStream = _fakeStream; return(0); } _fileStream.BytesWritten += IntEventArgsHandler; outStream = _fileStream; } else { _doneRate += 1.0f / _filesCount; var iea = new FileInfoEventArgs(_extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate)); FileExtractionStarted?.Invoke(this, iea); if (iea.Cancel) { Canceled = true; return(-1); } if (iea.Skip) { outStream = _fakeStream; return(0); } if (!Directory.Exists(fileName)) { try { Directory.CreateDirectory(fileName); } catch (Exception e) { AddException(e); } outStream = _fakeStream; } } } else { outStream = _fakeStream; } } else { // Extraction to a stream. if (index == _fileIndex) { outStream = _fileStream; _fileIndex = null; } else { outStream = _fakeStream; } } } return(0); }
bool IPlatformService.IsFileExists(string path) => FileExists?.Invoke(path) ?? false;
public async Task DownloadAsync(Uri address, string directory, string fileName, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); DownloadContext downloadContext = new DownloadContext(); if (!_uriContexts.TryAdd(address, downloadContext)) { throw new ApplicationException("The url is downloading."); } try { using (cancellationToken.Register(CancelAsync)) using (Stream responseStream = await OpenReadTaskAsync(address).ConfigureAwait(false)) { HttpWebResponse response = _uriContexts[address].Response; if (fileName.IsNullOrEmpty()) { fileName = response.GetContentDispositionFileName() ?? Path.GetFileName(response.ResponseUri.AbsolutePath) ?? throw new ArgumentException("fileName"); } string fullPath = Path.Combine(directory, fileName); FileMode fileMode = FileMode.Create; FileInfo file = new FileInfo(fullPath); if (file.Exists) { FileExistsContext fileExistsContext = new FileExistsContext(response.ResponseUri, fullPath) { FileExistsHandling = _defaultFileExistsHandling, }; FileExists?.Invoke(this, new EventArgs <FileExistsContext>(fileExistsContext)); switch (fileExistsContext.FileExistsHandling) { case FileExistsHandling.Ignore: return; case FileExistsHandling.Resume: if (file.Length >= response.ContentLength) { return; } fileMode = FileMode.OpenOrCreate; downloadContext.CurrentFileLength = file.Length; break; case FileExistsHandling.Rename: do { string newFileName = "{0} - New{1}".FormatWith( Path.GetFileNameWithoutExtension(fullPath), Path.GetExtension(fullPath)); fullPath = Path.Combine(directory, newFileName); file = new FileInfo(fullPath); } while (file.Exists); break; } } using (FileStream fileStream = new FileStream(fullPath, fileMode)) { if (downloadContext.CurrentFileLength > 0 && downloadContext.Response.IsRangeSupported()) { fileStream.Seek(downloadContext.CurrentFileLength, SeekOrigin.Begin); } await responseStream.CopyToAsync(fileStream).ConfigureAwait(false); await fileStream.FlushAsync().ConfigureAwait(false); } } } finally { _uriContexts.TryRemove(address, out DownloadContext value); } }