Sensenet: загрузка файлов через клиентский API Sensenet

Я пытаюсь получить поток файла, который существует в sensnet, через ClientAPI. Но я не нашел никаких документов об этом. Я также пытался использовать вызовы SenseNET API RestCaller, но я не знаю, как получить ввод параметр FieldID... через путь к файлу (например: /Root/Sites/Test/file.txt)

У меня есть API-интерфейс сервера, который инкапсулирует содержимое sensnet из клиентского приложения. Таким образом, все запросы в sensenet выполняются на стороне сервера. Я пытался получить потоковый файл с contentId... Но он не приносит идентификатор Content.Result (объект, который приносит идентификатор (я думаю...)). Например, возврат:

content = Id = 1016, Status = WaitingForActivation, Method = "{null}", Result = "{Ещё не вычислено}"

Вот мой код:

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());
        }

person Luciano Valinho    schedule 03.02.2017    source источник


Ответы (3)


Аналогичный пример, полностью асинхронный. По возможности не преобразовывайте асинхронные вызовы API в синхронные вызовы. Даже в среде ASP.NET должна быть возможность разрабатывать ваши методы как асинхронные, вместо того, чтобы заставлять их выполняться синхронно.

Пример ниже представляет собой метод асинхронного контроллера MVC. Сначала он получает идентификатор файла (конечно, вы можете пропустить это, если у вас уже есть идентификатор файла), затем загружает поток и немедленно записывает байты в выходной поток.

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();
}

Вы можете сделать то же самое в HttpTaskAsyncHandler или на асинхронной странице ASP.NET, если вы не используете MVC. Пожалуйста, сообщите нам больше о вашей среде и бизнес-кейсе, если вы хотите, чтобы мы предоставили более подробный пример.

person Miklós Tóth    schedule 11.02.2017

Чтобы решить мою конкретную проблему, мне пришлось создать задачу, возвращающую ее напрямую.

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();
person Luciano Valinho    schedule 09.02.2017
comment
Есть несколько проблем с этим. Например, следует ожидать Content.LoadAsync, и его нельзя использовать в операторе using. Делать асинхронный API синхронным — плохая практика, старайтесь избегать этого. Также желательно работать с потоками вместо байтового массива, чтобы не держать большие файлы в памяти. Если вы хотите, чтобы ваши пользователи загружали файлы, вы должны просто напрямую написать в OutputStream — пожалуйста, взгляните на мой ответ в качестве примера и дайте мне знать больше о вашем случае :-) - person Miklós Tóth; 11.02.2017

Я предполагаю, что вы имели в виду fileId под FieldID. Ваш файл для загрузки обычно выбирается из списка в пользовательском интерфейсе. Лучший вариант, который я могу порекомендовать, - это получить идентификатор файла вместе с другими его свойствами, используемыми для отображения в списке. Затем вы просто получаете выбранный файл из списка, который теперь имеет идентификатор. Надеюсь, я помог...

person L. Ivicz    schedule 03.02.2017
comment
Можно ли сделать загрузку файла полностью синхронной? - person Luciano Valinho; 06.02.2017