public DownloadFile ( IDocument remoteDocument, Stream localFileStream, |
||
remoteDocument | IDocument | Remote document. |
localFileStream | Stream | Local taget file stream. |
transmission | Transmission status. | |
hashAlg | Hash algoritm, which should be used to calculate hash of the uploaded stream content | |
update | UpdateChecksum | |
return | void |
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);
}
}
}
public void NormalDownload() { double lastPercent = 0; this.transmission.AddPositionConstraint(Is.LessThanOrEqualTo(this.remoteLength)); this.transmission.AddLengthConstraint(Is.EqualTo(this.remoteLength).Or.EqualTo(0)); this.transmission.PropertyChanged += delegate(object sender, System.ComponentModel.PropertyChangedEventArgs e) { var t = sender as Transmission; if (e.PropertyName == Utils.NameOf(() => t.Percent)) { Assert.That(t.Percent, Is.Null.Or.GreaterThanOrEqualTo(lastPercent)); lastPercent = t.Percent.GetValueOrDefault(); } }; using (IFileDownloader downloader = new SimpleFileDownloader()) { downloader.DownloadFile(this.mockedDocument.Object, this.localFileStream, this.transmission, this.hashAlg); Assert.AreEqual(this.remoteContent.Length, this.localFileStream.Length); Assert.AreEqual(SHA1Managed.Create().ComputeHash(this.remoteContent), this.hashAlg.Hash); Assert.AreEqual(SHA1Managed.Create().ComputeHash(this.localFileStream.ToArray()), this.hashAlg.Hash); } }