0

I've been fighting against the Dropbox API and I've made my little steps (I'm new on C#). The thing is that I've finally reached a file on my Dropbox account but I don't know how to create it on my local machine through StreamWriter.

Note: I know the await thing and so on could be easily improved, but I'm still getting into it :'D

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dropbox.Api;

namespace Try1Dropbox
{
    class Program
    {
        private const string ApiKey = "$$longChickenToken%%!!xD";

        static void Main(string[] args)
        {
            try
            {
                var task = Task.Run(async () => await Program.Run());
                task.Wait();
            }
            catch (AggregateException ex)
            {
                var inner = ex.InnerException;
                Console.WriteLine(inner.Message);
                Console.ReadKey();
            }
        }

        static async Task Run()
        {
            using (var dbx = new DropboxClient(ApiKey))
            {
                var full = await dbx.Users.GetCurrentAccountAsync();
                await ListRootFolder(dbx);
                Console.WriteLine("{0} - {1}", full.Name.DisplayName, full.Email);
                Console.ReadKey();
                await Download(dbx, @"/", "remotefile.pdf");
            }
        }

        private static async Task ListRootFolder(DropboxClient dbx)
        {
            var list = await dbx.Files.ListFolderAsync(string.Empty);

            // Show folders,  then files
            foreach (var item in list.Entries.Where(i => i.IsFolder))
            {
                Console.WriteLine("D  {0}/", item.Name);
            }
            foreach (var item in list.Entries.Where(i => i.IsFile))
            {
                Console.WriteLine("F{0,8} {1}", item.AsFile.Size, item.Name);
            }
        }

        private static async Task Download(DropboxClient dbx, string folder, string file)
        {
            string path = System.IO.Path.Combine(folder, file);
            var args = new Dropbox.Api.Files.DownloadArg(path);
            using (var response = await dbx.Files.DownloadAsync(args))
            {
                using (var sw = new System.IO.StreamWriter(@"c:\prueba\localtest.pdf"))
                {
                    Console.WriteLine(await response.GetContentAsStringAsync());
                    sw.Write(response.GetContentAsByteArrayAsync());

                    Console.ReadKey();
                }
            }
        }
    }
}

The point goes to sw.Write, where I "try to insert" the response I get on console but I just get this "System.Threading.Tasks.Task`1[System.Byte[]]" instead.

Thanks in advance and sorry for the n00bance. New on C# and Dropbox API.

peval27
  • 1,239
  • 2
  • 14
  • 40
Gonzo345
  • 1,133
  • 3
  • 20
  • 42
  • WriteLine is printing the String representation of the Task object returned. Split that call into `var response = await response...` and then print whatever Property of it you want printed. – Fildor Jan 30 '17 at 13:01

3 Answers3

2

You have written the following:

sw.Write(response.GetContentAsByteArrayAsync());

Anyway, the signature of the method is

Task<byte[]> GetContentAsByteArrayAsync()

Hence, you are passing a Task<byte[]> to sw.Write(...). The default behavior of StreamWriter.Write - for an object passed - is to write the text representation of an object - which is the type name for many classes - this is what you've seen. Furthermore you did forget to await the async operation, hence you've got a Task<byte[]>. You'll have to await the call in order to obtain the actual byte[] and not the Task<byte[]>. See the call to GetContentAsStringAsync.

Since you'd like to write an array of bytes here, you don't need a StreamWriter, but can operate on raw (well not exactly, but more raw than a StreamWriter) streams.

using (var stream = File.OpenWrite(@"c:\prueba\localtest.pdf"))
{
    Console.WriteLine(await response.GetContentAsStringAsync());

    var dataToWrite = await response.GetContentAsByteArrayAsync();
    stream.Write(dataToWrite, 0, dataToWrite.Length);

    Console.ReadKey();
}
Paul Kertscher
  • 9,416
  • 5
  • 32
  • 57
0

Looking at Dropbox API docs, the GetContentAsStringAsync() method being async returns Task<string>. Console.Writeline will simply call Task<string>.ToString() and what you see is the default implementation of the ToString() method. What you want to write is the actual result:

var taskResult = await response.GetContentAsStringAsync();

Console.WriteLine(taskResult.Result);

You caN find more information on MSDN

peval27
  • 1,239
  • 2
  • 14
  • 40
0

Okay, I finally found a solution!

private static async Task Download(DropboxClient dbx, string folder, string file)
{
    string path = Path.Combine(folder, file);
    var args = new Dropbox.Api.Files.DownloadArg(path);
    using (var response = await dbx.Files.DownloadAsync(args))
    {
        using (var sw = new StreamWriter(@"c:\prueba\localfile.pdf"))
        {
            Console.WriteLine(await response.GetContentAsStringAsync());
            var bytes = await response.GetContentAsByteArrayAsync();
            await sw.BaseStream.WriteAsync(bytes, 0, bytes.Length);
            Console.ReadKey();
        }
    }
}

Okay, the ToString magic wasn't all that magic XD Thanks guys!

Gonzo345
  • 1,133
  • 3
  • 20
  • 42
  • 1
    Please see my answer: You did forget the `await` and passed a `Task` to `sw.Write(...)`. The `ToString` is not weird at all. – Paul Kertscher Jan 30 '17 at 13:15
  • it's not weird. `Console.Writeline` will simply call `(Task).ToString()` and what you see is the default implementation of the `ToString()` method. – peval27 Jan 30 '17 at 13:16
  • @PaulKertscher Thanks for all! Useful as well! I feel like having a swiss-army-knife and just "knowing" how to use the big key... – Gonzo345 Jan 30 '17 at 13:18