Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Added support for partial file download [SPRNETSOCIALDB-10]
Browse files Browse the repository at this point in the history
  • Loading branch information
bbaia committed Nov 9, 2012
1 parent 621cb85 commit f60920b
Show file tree
Hide file tree
Showing 5 changed files with 272 additions and 1 deletion.
4 changes: 4 additions & 0 deletions doc/reference/src/api.xml
Expand Up @@ -80,6 +80,10 @@ IDropbox dropboxApi = serviceProvider.GetApi(accessToken.Value, accessToken.Secr
DropboxFile DownloadFile(string path, string revision);
DropboxFile DownloadPartialFile(string path, long startOffset, long length);
DropboxFile DownloadPartialFile(string path, long startOffset, long length, string revision);
DeltaPage Delta(string cursor);
Entry GetMetadata(string path);
Expand Down
2 changes: 1 addition & 1 deletion doc/reference/src/index.xml
Expand Up @@ -13,7 +13,7 @@
<!-- auto-generated -->
<copyright>Copyright 2012 SpringSource</copyright>
<!-- auto-generated -->
<pubdate>Last Updated 11/3/2012</pubdate>
<pubdate>Last Updated 11/9/2012</pubdate>
<authorgroup>
<author>
<firstname>Bruno</firstname>
Expand Down
96 changes: 96 additions & 0 deletions src/Spring.Social.Dropbox/Social/Dropbox/Api/IDropbox.cs
Expand Up @@ -212,6 +212,40 @@ public interface IDropbox : IApiBinding
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
Task<DropboxFile> DownloadFileAsync(string path, string revision, CancellationToken cancellationToken);

/// <summary>
/// Asynchronously downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <returns>
/// A 'Task' that represents the asynchronous operation that can return
/// a <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
Task<DropboxFile> DownloadPartialFileAsync(string path, long startOffset, long length);

/// <summary>
/// Asynchronously downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <param name="revision">
/// The revision of the file to retrieve, or <see langword="null"/> for the latest version.
/// </param>
/// <param name="cancellationToken">
/// The <see cref="CancellationToken"/> that will be assigned to the task.
/// <para/>
/// Use <see cref="P:CancellationToken.None"/> for an empty <see cref="CancellationToken"/> value.
/// </param>
/// <returns>
/// A 'Task' that represents the asynchronous operation that can return
/// a <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
Task<DropboxFile> DownloadPartialFileAsync(string path, long startOffset, long length, string revision, CancellationToken cancellationToken);

/// <summary>
/// Asynchronously keeps up with changes to files and folders in a user's Dropbox.
/// <para/>
Expand Down Expand Up @@ -501,6 +535,33 @@ public interface IDropbox : IApiBinding
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
DropboxFile DownloadFile(string path, string revision);

/// <summary>
/// Downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <returns>
/// A <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
DropboxFile DownloadPartialFile(string path, long startOffset, long length);

/// <summary>
/// Downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <param name="revision">
/// The revision of the file to retrieve, or <see langword="null"/> for the latest version.
/// </param>
/// <returns>
/// A <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
DropboxFile DownloadPartialFile(string path, long startOffset, long length, string revision);

/// <summary>
/// Keeps up with changes to files and folders in a user's Dropbox.
/// <para/>
Expand Down Expand Up @@ -829,6 +890,41 @@ public interface IDropbox : IApiBinding
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
RestOperationCanceler DownloadFileAsync(string path, string revision, Action<RestOperationCompletedEventArgs<DropboxFile>> operationCompleted);

/// <summary>
/// Asynchronously downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <param name="operationCompleted">
/// The 'Action&lt;&gt;' to perform when the asynchronous request completes.
/// Provides <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </param>
/// <returns>
/// A <see cref="RestOperationCanceler"/> instance that allows to cancel the asynchronous operation.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
RestOperationCanceler DownloadPartialFileAsync(string path, long startOffset, long length, Action<RestOperationCompletedEventArgs<DropboxFile>> operationCompleted);

/// <summary>
/// Asynchronously downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <param name="revision">
/// The revision of the file to retrieve, or <see langword="null"/> for the latest version.
/// </param>
/// <param name="operationCompleted">
/// The 'Action&lt;&gt;' to perform when the asynchronous request completes.
/// Provides <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </param>
/// <returns>
/// A <see cref="RestOperationCanceler"/> instance that allows to cancel the asynchronous operation.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
RestOperationCanceler DownloadPartialFileAsync(string path, long startOffset, long length, string revision, Action<RestOperationCompletedEventArgs<DropboxFile>> operationCompleted);

/// <summary>
/// Asynchronously keeps up with changes to files and folders in a user's Dropbox.
/// <para/>
Expand Down
132 changes: 132 additions & 0 deletions src/Spring.Social.Dropbox/Social/Dropbox/Api/Impl/DropboxTemplate.cs
Expand Up @@ -325,6 +325,53 @@ public Task<DropboxFile> DownloadFileAsync(string path, string revision, Cancell
return this.RestTemplate.ExecuteAsync<DropboxFile>(this.BuildDownloadUrl(path, revision), HttpMethod.GET, requestCallback, responseExtractor, cancellationToken);
}

/// <summary>
/// Asynchronously downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <returns>
/// A 'Task' that represents the asynchronous operation that can return
/// a <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
public Task<DropboxFile> DownloadPartialFileAsync(string path, long startOffset, long length)
{
return this.DownloadPartialFileAsync(path, startOffset, length, null, CancellationToken.None);
}

/// <summary>
/// Asynchronously downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <param name="revision">
/// The revision of the file to retrieve, or <see langword="null"/> for the latest version.
/// </param>
/// <param name="cancellationToken">
/// The <see cref="CancellationToken"/> that will be assigned to the task.
/// <para/>
/// Use <see cref="P:CancellationToken.None"/> for an empty <see cref="CancellationToken"/> value.
/// </param>
/// <returns>
/// A 'Task' that represents the asynchronous operation that can return
/// a <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
public Task<DropboxFile> DownloadPartialFileAsync(string path, long startOffset, long length, string revision, CancellationToken cancellationToken)
{
HttpEntity requestEntity = new HttpEntity();
requestEntity.Headers.Add("Range", String.Format("bytes={0}-{1}", startOffset, startOffset + length - 1));
return this.RestTemplate.ExchangeAsync<DropboxFile>(
this.BuildDownloadUrl(path, revision), HttpMethod.GET, requestEntity, cancellationToken)
.ContinueWith<DropboxFile>(task =>
{
return task.Result.Body;
});
}

/// <summary>
/// Asynchronously keeps up with changes to files and folders in a user's Dropbox.
/// <para/>
Expand Down Expand Up @@ -728,6 +775,42 @@ public DropboxFile DownloadFile(string path, string revision)
return this.RestTemplate.Execute<DropboxFile>(this.BuildDownloadUrl(path, revision), HttpMethod.GET, requestCallback, responseExtractor);
}

/// <summary>
/// Downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <returns>
/// A <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
public DropboxFile DownloadPartialFile(string path, long startOffset, long length)
{
return this.DownloadPartialFile(path, startOffset, length, null);
}

/// <summary>
/// Downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <param name="revision">
/// The revision of the file to retrieve, or <see langword="null"/> for the latest version.
/// </param>
/// <returns>
/// A <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
public DropboxFile DownloadPartialFile(string path, long startOffset, long length, string revision)
{
HttpEntity requestEntity = new HttpEntity();
requestEntity.Headers.Add("Range", String.Format("bytes={0}-{1}", startOffset, startOffset + length - 1));
return this.RestTemplate.Exchange<DropboxFile>(
this.BuildDownloadUrl(path, revision), HttpMethod.GET, requestEntity).Body;
}

/// <summary>
/// Keeps up with changes to files and folders in a user's Dropbox.
/// <para/>
Expand Down Expand Up @@ -1175,6 +1258,55 @@ public RestOperationCanceler DownloadFileAsync(string path, string revision, Act
return this.RestTemplate.ExecuteAsync<DropboxFile>(this.BuildDownloadUrl(path, revision), HttpMethod.GET, requestCallback, responseExtractor, operationCompleted);
}

/// <summary>
/// Asynchronously downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <param name="operationCompleted">
/// The 'Action&lt;&gt;' to perform when the asynchronous request completes.
/// Provides <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </param>
/// <returns>
/// A <see cref="RestOperationCanceler"/> instance that allows to cancel the asynchronous operation.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
public RestOperationCanceler DownloadPartialFileAsync(string path, long startOffset, long length, Action<RestOperationCompletedEventArgs<DropboxFile>> operationCompleted)
{
return this.DownloadPartialFileAsync(path, startOffset, length, null, operationCompleted);
}

/// <summary>
/// Asynchronously downloads part of a file and its metadata.
/// </summary>
/// <param name="path">The Dropbox path to the file you want to retrieve, relative to root.</param>
/// <param name="startOffset">The zero-based starting position of the part file.</param>
/// <param name="length">The number of bytes of the part file.</param>
/// <param name="revision">
/// The revision of the file to retrieve, or <see langword="null"/> for the latest version.
/// </param>
/// <param name="operationCompleted">
/// The 'Action&lt;&gt;' to perform when the asynchronous request completes.
/// Provides <see cref="DropboxFile"/> object containing the part of file's content and metadata.
/// </param>
/// <returns>
/// A <see cref="RestOperationCanceler"/> instance that allows to cancel the asynchronous operation.
/// </returns>
/// <exception cref="DropboxApiException">If there is an error while communicating with Dropbox.</exception>
public RestOperationCanceler DownloadPartialFileAsync(string path, long startOffset, long length, string revision, Action<RestOperationCompletedEventArgs<DropboxFile>> operationCompleted)
{
HttpEntity requestEntity = new HttpEntity();
requestEntity.Headers.Add("Range", String.Format("bytes={0}-{1}", startOffset, startOffset + length - 1));
return this.RestTemplate.ExchangeAsync<DropboxFile>(
this.BuildDownloadUrl(path, revision), HttpMethod.GET, requestEntity,
r =>
{
operationCompleted(new RestOperationCompletedEventArgs<DropboxFile>(
r.Error == null ? r.Response.Body : null, r.Error, r.Cancelled, r.UserState));
});
}

/// <summary>
/// Asynchronously keeps up with changes to files and folders in a user's Dropbox.
/// <para/>
Expand Down
Expand Up @@ -321,6 +321,45 @@ public void DownloadFile()
Assert.IsNull(file.Metadata.Contents);
}

[Test]
public void DownloadPartialFile()
{
responseHeaders["x-dropbox-metadata"] = "{ \"size\": \"225.4KB\", \"rev\": \"35e97029684fe\", \"thumb_exists\": false, \"bytes\": 230783, \"modified\": \"Tue, 19 Jul 2011 21:55:38 +0000\", \"path\": \"/Getting_Started.pdf\", \"is_dir\": false, \"icon\": \"page_white_acrobat\", \"root\": \"dropbox\", \"mime_type\": \"application/pdf\", \"revision\": 220823 }";
responseHeaders.ContentType = MediaType.TEXT_PLAIN;
mockServer.ExpectNewRequest()
.AndExpectUri("https://api-content.dropbox.com/1/files/dropbox/Dir/File.txt?rev=a123z")
.AndExpectMethod(HttpMethod.GET)
.AndExpectHeader("Range", "bytes=0-1023")
.AndRespondWith(EmbeddedResource("File.txt"), responseHeaders);

#if NET_4_0 || SILVERLIGHT_5
DropboxFile file = dropbox.DownloadPartialFileAsync("Dir/File.txt", 0, 1024, "a123z", CancellationToken.None).Result;
#else
DropboxFile file = dropbox.DownloadPartialFile("Dir/File.txt", 0, 1024, "a123z");
#endif
Assert.IsNotNull(file);

// Content
Assert.IsNotNull(file.Content);
Assert.IsNotEmpty(file.Content);

// Metadata
Assert.AreEqual(230783, file.Metadata.Bytes);
Assert.IsNull(file.Metadata.Hash);
Assert.AreEqual("page_white_acrobat", file.Metadata.Icon);
Assert.AreEqual(false, file.Metadata.IsDeleted);
Assert.AreEqual(false, file.Metadata.IsDirectory);
Assert.AreEqual("application/pdf", file.Metadata.MimeType);
Assert.IsNotNull(file.Metadata.ModifiedDate);
Assert.AreEqual("19/07/2011 21:55:38", file.Metadata.ModifiedDate.Value.ToUniversalTime().ToString("dd'/'MM'/'yyyy HH:mm:ss"));
Assert.AreEqual("/Getting_Started.pdf", file.Metadata.Path);
Assert.AreEqual("35e97029684fe", file.Metadata.Revision);
Assert.AreEqual("dropbox", file.Metadata.Root);
Assert.AreEqual("225.4KB", file.Metadata.Size);
Assert.IsFalse(file.Metadata.ThumbExists);
Assert.IsNull(file.Metadata.Contents);
}

[Test]
public void Delta()
{
Expand Down

0 comments on commit f60920b

Please sign in to comment.