/// <summary> /// Get the content for the client brand file /// </summary> /// <param name="pathname">Client brand file path</param> /// <param name="output">Stream to hold the client brand file</param> /// <returns>Whether to get the content for the client brand file</returns> public bool GetFile(string pathname, Stream output) { if (this.session == null) { return(false); } try { IDocument doc = this.session.GetObjectByPath(pathname) as IDocument; if (doc == null) { return(false); } DotCMIS.Data.IContentStream contentStream = doc.GetContentStream(); if (contentStream == null) { return(false); } contentStream.Stream.CopyTo(output); return(true); } catch (Exception e) { Logger.Debug(e.Message); return(false); } }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="status">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile(IDocument remoteDocument, Stream localFileStream, FileTransmissionEvent status, HashAlgorithm hashAlg) { long?fileLength = remoteDocument.ContentStreamLength; DotCMIS.Data.IContentStream contentStream = remoteDocument.GetContentStream(); // Skip downloading empty content, just go on with an empty file if (null == fileLength || fileLength == 0 || contentStream == null) { hashAlg.TransformFinalBlock(new byte[0], 0, 0); return; } using (ProgressStream progressStream = new ProgressStream(localFileStream, status)) using (CryptoStream hashstream = new CryptoStream(progressStream, hashAlg, CryptoStreamMode.Write)) using (Stream remoteStream = contentStream.Stream) { status.ReportProgress(new TransmissionProgressEventArgs { Length = remoteDocument.ContentStreamLength, ActualPosition = 0 }); byte[] buffer = new byte[8 * 1024]; int len; while ((len = remoteStream.Read(buffer, 0, buffer.Length)) > 0) { lock (this.disposeLock) { if (this.disposed) { status.ReportProgress(new TransmissionProgressEventArgs { Aborted = true }); throw new ObjectDisposedException(status.Path); } hashstream.Write(buffer, 0, len); hashstream.Flush(); } } } }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="transmission">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, UpdateChecksum update = null) { byte[] buffer = new byte[8 * 1024]; int len; if (localFileStream.Length > 0) { localFileStream.Seek(0, SeekOrigin.Begin); while ((len = localFileStream.Read(buffer, 0, buffer.Length)) > 0) { hashAlg.TransformBlock(buffer, 0, len, buffer, 0); } } long offset = localFileStream.Position; long?fileLength = remoteDocument.ContentStreamLength; if (fileLength <= offset) { transmission.Length = fileLength.GetValueOrDefault(); transmission.Position = offset; hashAlg.TransformFinalBlock(new byte[0], 0, 0); return; } DotCMIS.Data.IContentStream contentStream = null; if (offset > 0) { long remainingBytes = (long)fileLength - offset; transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes); } else { contentStream = remoteDocument.GetContentStream(); } using (var transmissionStream = transmission.CreateStream(localFileStream)) using (CryptoStream hashstream = new CryptoStream(transmissionStream, hashAlg, CryptoStreamMode.Write)) using (Stream remoteStream = contentStream != null ? contentStream.Stream : new MemoryStream(0)) { transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; int written = 0; while ((len = remoteStream.Read(buffer, 0, buffer.Length)) > 0) { lock (this.disposeLock) { if (this.disposed) { transmission.Status = TransmissionStatus.ABORTED; throw new ObjectDisposedException(transmission.Path); } try { hashstream.Write(buffer, 0, len); hashstream.Flush(); written += len; } catch (Exception) { this.UpdateHash(hashAlg, localFileStream.Length, update); throw; } if (written >= 1024 * 1024) { this.UpdateHash(hashAlg, localFileStream.Length, update); written = 0; } } } if (written > 0) { this.UpdateHash(hashAlg, localFileStream.Length, update); } } }
/** * Download a single file from the CMIS server. */ private void DownloadFile(IDocument remoteDocument, string localFolder) { activityListener.ActivityStarted(); if (remoteDocument.ContentStreamLength == 0) { Logger.Info("CmisDirectory | Skipping download of file with null content stream: " + remoteDocument.ContentStreamFileName); activityListener.ActivityStopped(); return; } StreamWriter localfile = null; DotCMIS.Data.IContentStream contentStream = null; string filepath = Path.Combine(localFolder, remoteDocument.ContentStreamFileName); // If a file exist, file is deleted. if (File.Exists(filepath)) { File.Delete(filepath); } string tmpfilepath = filepath + ".sync"; // Download file, starting at the last download point Boolean success = false; try { // Get the last position in the localfile. By default position 0 (Nuxeo do not support partial getContentStream #107 Int64 Offset = 0; // Nuxeo don't support partial getContentStream if (session.RepositoryInfo.VendorName.ToLower().Contains("nuxeo")) { Logger.Warn("CmisDirectory | Nuxeo does not support partial download, so restart from zero."); localfile = new StreamWriter(tmpfilepath); contentStream = remoteDocument.GetContentStream(); } else { // Create Stream with the local file in append mode, if file is empty it's like a full download (Offset 0) localfile = new StreamWriter(tmpfilepath, true); localfile.AutoFlush = true; Offset = localfile.BaseStream.Position; contentStream = remoteDocument.GetContentStream(remoteDocument.Id, Offset, remoteDocument.ContentStreamLength); } if (contentStream == null) { Logger.Warn("CmisDirectory | Skipping download of file with null content stream: " + remoteDocument.ContentStreamFileName); throw new IOException(); } Logger.Info(String.Format("CmisDirectory | Start download of file with offset {0}", Offset)); contentStream.Stream.Flush(); CopyStream(contentStream.Stream, localfile.BaseStream); localfile.Flush(); localfile.Close(); contentStream.Stream.Close(); success = true; } catch (Exception ex) { Logger.Fatal(String.Format("CmisDirectory | Download of file {0} abort: {1}", remoteDocument.ContentStreamFileName, ex)); success = false; if (localfile != null) { localfile.Flush(); localfile.Close(); File.Delete(tmpfilepath); } if (contentStream != null) { contentStream.Stream.Close(); } } try { // Rename file // TODO - Yannick - Control file integrity by using hash compare - Is it necessary ? if (success) { File.Move(tmpfilepath, filepath); // Get metadata. Dictionary <string, string[]> metadata = FetchMetadata(remoteDocument); // Create database entry for this file. database.AddFile(filepath, remoteDocument.LastModificationDate, metadata); } } catch (Exception ex) { Logger.Fatal("CmisDirectory | Unable to write metadata in the CmisDatabase: " + ex.ToString()); } activityListener.ActivityStopped(); }