/// <summary> /// Download a file, without retrying. /// </summary> private void DownloadStream(DotCMIS.Data.IContentStream contentStream, string filePath) { using (Stream file = File.OpenWrite(filePath)) { byte[] buffer = new byte[8 * 1024]; int len; while ((len = contentStream.Stream.Read(buffer, 0, buffer.Length)) > 0) { file.Write(buffer, 0, len); } } contentStream.Stream.Close(); }
/// <summary> /// Download a file, without retrying. /// </summary> private byte[] DownloadStream(DotCMIS.Data.IContentStream contentStream, string filePath) { byte[] hash = { }; using (Stream file = File.OpenWrite(filePath)) using (SHA1 hashAlg = new SHA1Managed()) using (CryptoStream hashstream = new CryptoStream(file, hashAlg, CryptoStreamMode.Write)) { byte[] buffer = new byte[8 * 1024]; int len; while ((len = contentStream.Stream.Read(buffer, 0, buffer.Length)) > 0) { hashstream.Write(buffer, 0, len); } hashstream.FlushFinalBlock(); hash = hashAlg.Hash; } contentStream.Stream.Close(); return(hash); }
/// <summary> /// Download a single file from the CMIS server. /// </summary> private bool DownloadFile(IDocument remoteDocument, string localFolder) { sleepWhileSuspended(); string fileName = remoteDocument.ContentStreamFileName; Logger.Info("Downloading: " + fileName); // Skip if invalid file name. See https://github.com/nicolas-raoul/CmisSync/issues/196 if (Utils.IsInvalidFileName(fileName)) { Logger.Info("Skipping download of file with illegal filename: " + fileName); return(true); } try { DotCMIS.Data.IContentStream contentStream = null; string filepath = Path.Combine(localFolder, fileName); string tmpfilepath = filepath + ".sync"; // If there was previously a directory with this name, delete it. // TODO warn if local changes inside the folder. if (Directory.Exists(filepath)) { Directory.Delete(filepath); } // If file exists, delete it. File.Delete(filepath); File.Delete(tmpfilepath); // Download file. Boolean success = false; byte[] filehash = { }; try { contentStream = remoteDocument.GetContentStream(); // If this file does not have a content stream, ignore it. // Even 0 bytes files have a contentStream. // null contentStream sometimes happen on IBM P8 CMIS server, not sure why. if (contentStream == null) { Logger.Warn("Skipping download of file with null content stream: " + fileName); return(true); } // Skip downloading the content, just go on with an empty file if (remoteDocument.ContentStreamLength == 0) { Logger.Info("Skipping download of file with content length zero: " + fileName); using (FileStream s = File.Create(tmpfilepath)) { s.Close(); } } else { filehash = DownloadStream(contentStream, tmpfilepath); contentStream.Stream.Close(); } success = true; } catch (CmisBaseException e) { ProcessRecoverableException("Download failed: " + fileName, e); if (contentStream != null) { contentStream.Stream.Close(); } success = false; File.Delete(tmpfilepath); } if (success) { Logger.Info("Downloaded: " + fileName); // TODO Control file integrity by using hash compare? // Get metadata. Dictionary <string, string[]> metadata = null; try { metadata = FetchMetadata(remoteDocument); } catch (CmisBaseException e) { ProcessRecoverableException("Could not fetch metadata: " + fileName, e); // Remove temporary local document to avoid it being considered a new document. File.Delete(tmpfilepath); return(false); } // Remove the ".sync" suffix. File.Move(tmpfilepath, filepath); if (null != remoteDocument.CreationDate) { File.SetCreationTime(filepath, (DateTime)remoteDocument.CreationDate); } if (null != remoteDocument.LastModificationDate) { File.SetLastWriteTime(filepath, (DateTime)remoteDocument.LastModificationDate); } // Create database entry for this file. database.AddFile(filepath, remoteDocument.LastModificationDate, metadata, filehash); Logger.Info("Added file to database: " + filepath); } return(success); } catch (Exception e) { ProcessRecoverableException("Could not download file: " + Path.Combine(localFolder, fileName), e); return(false); } }
/// <summary> /// Download a single file from the CMIS server. /// </summary> private void DownloadFile(IDocument remoteDocument, string localFolder) { activityListener.ActivityStarted(); string fileName = remoteDocument.ContentStreamFileName; Logger.Info("Downloading: " + fileName); // TODO: Make this configurable. if (remoteDocument.ContentStreamLength == 0) { Logger.Info("Skipping download of file with content length zero: " + fileName); activityListener.ActivityStopped(); return; } // Skip if invalid file name. See https://github.com/nicolas-raoul/CmisSync/issues/196 if (Utils.IsInvalidFileName(fileName)) { Logger.Info("Skipping download of file with illegal filename: " + fileName); activityListener.ActivityStopped(); return; } try { DotCMIS.Data.IContentStream contentStream = null; string filepath = Path.Combine(localFolder, fileName); string tmpfilepath = filepath + ".sync"; // If there was previously a directory with this name, delete it. // TODO warn if local changes inside the folder. if (Directory.Exists(filepath)) { Directory.Delete(filepath); } // If file exists, delete it. File.Delete(filepath); File.Delete(tmpfilepath); // Download file. Boolean success = false; try { contentStream = remoteDocument.GetContentStream(); // If this file does not have a content stream, ignore it. // Even 0 bytes files have a contentStream. // null contentStream sometimes happen on IBM P8 CMIS server, not sure why. if (contentStream == null) { Logger.Warn("Skipping download of file with null content stream: " + fileName); activityListener.ActivityStopped(); return; } DownloadStream(contentStream, tmpfilepath); contentStream.Stream.Close(); success = true; } catch (Exception ex) { Logger.Error("Download failed: " + fileName + " " + ex); if (contentStream != null) { contentStream.Stream.Close(); } success = false; File.Delete(tmpfilepath); } if (success) { Logger.Info("Downloaded: " + fileName); // TODO Control file integrity by using hash compare? // Get metadata. Dictionary <string, string[]> metadata = null; try { metadata = FetchMetadata(remoteDocument); } catch (Exception e) { Logger.Info("Exception while fetching metadata: " + fileName + " " + Utils.ToLogString(e)); // Remove temporary local document to avoid it being considered a new document. File.Delete(tmpfilepath); activityListener.ActivityStopped(); return; } // Remove the ".sync" suffix. File.Move(tmpfilepath, filepath); // Create database entry for this file. database.AddFile(filepath, remoteDocument.LastModificationDate, metadata); Logger.Info("Added to database: " + fileName); } } catch (IOException e) { Logger.Warn("Exception while file operation: " + Utils.ToLogString(e)); } activityListener.ActivityStopped(); }