0

I'm trying to get the Stream of file that exists on sensenet through ClientAPI. But I didn't find any documentation about that. I also tried using the RestCaller SenseNET API Calls but I don't know how to get the input parameter FieldID... through the path of the file (ex: /Root/Sites/Test/file.txt)

I have an server api that encapsulates the sensenet content from the client application. So, the requests on sensenet are all on server side. I tried to get stream file with contentId... But It doesn't bring the ID of the Content.Result (object that brings the ID (I guess...)). For instance, the return is:

content = Id = 1016, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"

Here's my code:

var fileId = SenseNet.Client.Content.LoadAsync(parentPath).Result.Id;
        var req = RESTCaller.GetStreamRequest(fileId);

        try
        {
            using (var response = await req.GetResponseAsync())
            {
                using (var stream = response.GetResponseStream())
                {
                    using (var streamReader = new MemoryStream())
                    {
                        stream.CopyTo(streamReader);
                        return streamReader.ToArray();
                    }
                }
            }
        }
        catch (WebException webex)
        {
            throw await RESTCaller.GetClientExceptionAsync(webex, req.RequestUri.ToString());
        }

3 Answers3

1

A similar example, fully async. Please do not convert async API calls to synchronous calls if possible. Even in an ASP.NET environment it should be possible to design your methods as async, instead of forcing them to run synchronously.

The example below is an asynchronous MVC controller method. It gets the file id first (of course you can skip that if you already have a file id), than downloads the stream and immediately writes the bytes to the output stream.

public async Task DownloadAsync()
{
    var path = "/Root/YourDocuments/test1.txt";
    var fileContent = await SNC.Content.LoadAsync(path);
    var fileId = fileContent.Id;
    var req = SNC.RESTCaller.GetStreamRequest(fileId);

    Response.ClearContent();
    Response.AddHeader("content-disposition", $"attachment;filename={fileContent.Name}");
    Response.ContentType = "text/plain";
    Response.ContentEncoding = Encoding.UTF32;

    using (var response = await req.GetResponseAsync())
    {
        using (var stream = response.GetResponseStream())
        {
            await stream.CopyToAsync(Response.OutputStream);
        }
    }

    Response.End();
}

You can do the same in an HttpTaskAsyncHandler or on an async ASP.NET page too, if you do not use MVC. Please let us know more about your environment and business case if you want us to provide a more detailed example.

Miklós Tóth
  • 1,490
  • 13
  • 19
0

To resolve my specific problem I had to create the task returning it directly.

return Task.Factory.StartNew(() =>
        {

            using (var content = Content.LoadAsync(path))
            {
                var fileId = content.Result.Id;
                var req = RESTCaller.GetStreamRequest(fileId);

                using (var response = req.GetResponse())
                {
                    using (var stream = response.GetResponseStream())
                    {
                        using (var streamReader = new MemoryStream())
                        {
                            stream.CopyTo(streamReader);
                            return streamReader.ToArray();
                        }
                    }
                }
            }
        }).WaitAndUnwrapException();
  • There are a few problems with this. For example Content.LoadAsync should be "awaited" and cannot be used in a using statement. Making an async API synchronous is a bad practice, please try to avoid that. It is also advisable to work with streams instead of a byte array to avoid keeping large files in memory. If you want to let your users download files, you should simply write to the OutputStream directly - please take a look at my answer for an example, and let me know more about your case :-) – Miklós Tóth Feb 11 '17 at 16:34
-1

I assume you meant fileId by FieldID. Your file to download usually chosen from a list on UI. The best option I can recommend is that you should get the Id of the file as well along with its other properties used to show in the list. Then you just get the selected file from the list that now has the Id. I hope, I helped...

L. Ivicz
  • 130
  • 4