AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 09.08.2012, 12:18   #1  
AlexeyVS is offline
AlexeyVS
Участник
 
103 / 31 (2) +++
Регистрация: 02.04.2010
AX 2012 EP. Как скачать файл. Решение.
Добрый день, товарищи!

Предлагаю вашему вниманию решение проблемы закачки файлов с портала.
Это может пригодится, когда на портале формируется некий отчет, например в формате Excel, кладется в папку на сервере и его необходимо передать клиенту через браузер.
Должно работать так же, как работает стандартный диалог просмотра прикрепленных файлов.
Буду описывать свое решение. Конструктивная критика и предложения по улучшению механизма принимаются ))
За это сообщение автора поблагодарили: Ganna (1).
Старый 09.08.2012, 12:28   #2  
AlexeyVS is offline
AlexeyVS
Участник
 
103 / 31 (2) +++
Регистрация: 02.04.2010
Итак, начинаем готовить.

1. Пишем "ядро" загрузчика. Я дописал еще один метод в класс EPDocuGet, взяв за основу один из существующих методов.

X++:
#define.BUFFER_SIZE(4096)

static void runDownloadFile(Filename fileName)
{
    IISResponse response = new IISResponse();
    BinData binData;
    int fileOffset;
    str headerFileName;
    ;

    headerFileName = System.IO.Path::GetFileName(fileName);
    headerFileName = strReplace(headerFileName, ';', '_');
    headerFileName = strReplace(headerFileName, ' ', '_');
    headerFileName = System.Web.HttpUtility::UrlEncode(headerFileName);

    response.clear();
    response.contentType('application/Octet-Stream');
    response.addHeader('Content-Disposition', 'attachment;filename="' + headerFileName + '"');

    binData = new BinData();
    fileOffset = 0;
    new FileIOPermission(fileName, 'r').assert();

    while (true)
    {
        // BP Deviation Documented
        if (!binData.loadFile(fileName, fileOffset, #BUFFER_SIZE))
        {
            break;
        }

        fileOffset += #BUFFER_SIZE;
        EPDocuGet::writeToResponse(response, binData.getData());
    }
}
Здесь fileName это полный путь к файлу на сервере.
Старый 09.08.2012, 12:39   #3  
AlexeyVS is offline
AlexeyVS
Участник
 
103 / 31 (2) +++
Регистрация: 02.04.2010
2. Пишем специальную aspx-страницу для вызова загрузчика, например, downloadFile.aspx со следующим содержимым:

Код:
<%@ Page Language="C#" Trace="false" %>
<%@ Assembly Name="Microsoft.Dynamics.Framework.Portal, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" %>
<%@ Assembly Name="Microsoft.Dynamics.Framework.Data.Ax, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" %>
<%@ Assembly Name="Microsoft.Dynamics.Framework.BusinessConnector, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" %>
<%@ Assembly Name="Microsoft.Dynamics.Framework.BusinessConnector.Proxy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" %>
<%@ Assembly Name="Microsoft.Dynamics.Framework.Metadata.AX, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" %>
<%@ Import Namespace="Microsoft.Dynamics.Framework.Portal" %>
<%@ Import Namespace="Microsoft.Dynamics.Framework.Portal.UI" %>
<%@ Import Namespace="Microsoft.Dynamics.AX.Framework.Portal.Data" %>
<%@ Import Namespace="Microsoft.Dynamics.Framework.BusinessConnector.Proxy" %>
<%@ Import Namespace="Microsoft.Dynamics.Framework.BusinessConnector.Session" %>
<%@ Import Namespace="Microsoft.Dynamics.Framework.BusinessConnector.Adapter" %>
<%@ Import Namespace="Microsoft.Dynamics.AX.Framework.Services.Client" %>

<script runat="server">
    void Page_Load(object sender, EventArgs e)
    {
        AxSharepointWebSession session = null;
        string fileName = this.Request.QueryString["file"];
        
        try
        {
            session = SessionHelper.Instance.GetSharepointSession();
            
            if (session != null)
            {
                session.AxaptaAdapter.CallStaticClassMethod("EPDocuGet", "runDownloadFile", fileName);

                Response.Flush();
            }
        }
        catch (System.Exception)
        {
            // Current design is to not display errors to the user
            // Errors are stored in the event log for review by the site operator
        }
        finally
        {
            if (session != null)
            {
                SessionHelper.Instance.ReleaseSharepointSession(session);
            }
        }
    }
</script>
Страницу кладем на сервер в папку C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ep

Как видно, при загрузке этой страницы будет происходить получение имени файла из параметров запроса и вызов созданного в п. 1 метода с передачей ему имени файла.

3. Создаем в АОТ ссылку на эту страницу. Web\Web Menu ITems\URLs
Назовем ее DownloadFile.
В свойстве URL пишем: _layouts/ep/downloadFile.aspx
Старый 09.08.2012, 13:00   #4  
AlexeyVS is offline
AlexeyVS
Участник
 
103 / 31 (2) +++
Регистрация: 02.04.2010
4. Теперь все готово к тестированию.
Создаем файл для загрузки и кладем его на сервер, например, в c:\temp\test.xls
Будем его скачивать.

5. Далее нам понадобится VisualStudio.
Создаем веб-контрол для веб-парт страницы. Кладем туда кнопку и в обработчике нажатия кнопки пишем код:

Код:
AxUrlMenuItem getFileUrl = new AxUrlMenuItem("DownloadFile");
getFileUrl.ExtraParams.Add("file", "c:\\temp\\test.xls");
DialogHelper.Navigate(getFileUrl, this);
В реальной ситуации этот механизм используется примерно так:

Код:
protected void WebPart_ActionMenuItemClicked(object sender, ActionMenuItemEventArgs e)
    {
        string fileName = string.Empty;

        if (e.MenuItem.MenuItemAOTName == "WayBill")
        {
            fileName = (string)this.RunDatasetMethod("makeWayBill"); // вызов метода, который формирует отчет и кладет файл отчета в папку на сервере
        }
        
        if (!string.IsNullOrEmpty(fileName))
        {
            AxUrlMenuItem getFileUrl = new AxUrlMenuItem("DownloadFile");
            getFileUrl.ExtraParams.Add("file", fileName);

            DialogHelper.Navigate(getFileUrl, this);
        }
    }

private object RunDatasetMethod(string methodName, params object[] paramList)
    {
        object res = null;

        try
        {
            if (paramList.Length > 0)
            {
                res = this.AxDataSource1.GetDataSet().DataSetRun.AxaptaObjectAdapter.Call(methodName, paramList);
            }
            else
            {
                res = this.AxDataSource1.GetDataSet().DataSetRun.AxaptaObjectAdapter.Call(methodName);
            }
        }
        catch (System.Exception ex)
        {
            AxExceptionCategory exceptionCategory;

            if (!AxControlExceptionHandler.TryHandleException(this, ex, out exceptionCategory))
            {
                // Throw the fatal exception
                throw;
            }
        }

        return res;
    }
Таким образом, получаем универсальный механизм для работы с файлами в Ax 2012 EnterprisePortal.

Спасибо за внимание!
За это сообщение автора поблагодарили: MikeR (5), gl00mie (5),  (1).
Старый 09.08.2012, 13:16   #5  
Murlin is offline
Murlin
Возьми свет!!!
Аватар для Murlin
Самостоятельные клиенты AX
Злыдни
 
291 / 32 (2) +++
Регистрация: 22.09.2008
Адрес: Тюмень, Рашан Федерашан
Цитата:
Сообщение от AlexeyVS Посмотреть сообщение
4. Теперь все готово к тестированию
Спасибо за внимание!
перенес в четверку. что то не то творится с разрешениями файлов.
__________________
Axapta 3.0 sp 5 Oracle
Диплом Интернет-Университета Информационных Технологий: Основы бухгалтерского учета
Я могу взорвать вам мозг!!!
Старый 09.08.2012, 14:50   #6  
AlexeyVS is offline
AlexeyVS
Участник
 
103 / 31 (2) +++
Регистрация: 02.04.2010
Боюсь в 4ке это не будет работать (
Там используется более прозаический метод закачки файлов:

X++:
static void redirectFile(FileName _name)
{
    websession().redirectURL(strfmt('%1_layouts/EP/TEMP/%2', webSession().siteUrl(), _name));
}
Здесь, _name - имя файла без пути
Старый 09.08.2012, 15:59   #7  
Murlin is offline
Murlin
Возьми свет!!!
Аватар для Murlin
Самостоятельные клиенты AX
Злыдни
 
291 / 32 (2) +++
Регистрация: 22.09.2008
Адрес: Тюмень, Рашан Федерашан
Цитата:
Сообщение от AlexeyVS Посмотреть сообщение
Боюсь в 4ке это не будет работать (
Там используется более прозаический метод закачки файлов:
[/XPP]

Здесь, _name - имя файла без пути
странно метод runReport класса EPDocuGetWebLet
X++:
#define.BUFFER_SIZE(4096)
#File
client static void runReport(Common callerRecord, IISResponse response)
{
    Query                   query = new Query();
    QueryBuildDataSource    qbds;
    QueryRun                queryRun;
    EPSendDocument          document;
    BinData                 binData;
    str                     fileName;
    int                     fileOffset;
    DictTable               table = new DictTable(callerRecord.TableId);
    str                     tempFileName;
    boolean                 emptyReport;
    ;
    if (WebLet::hasTableAccess(callerRecord.TableId))
    {
        qbds = query.addDataSource(callerRecord.TableId);
        if (callerRecord && callerRecord.TableId != tablenum(DocuRef))
        {
            // Requery the record to test record level security
            qbds.addRange(table.fieldName2Id('RecId')).value(SysQuery::value(callerRecord.RecId));
            query.recordLevelSecurity(true);
            queryRun = new QueryRun(query);
            if (queryRun.next())
            {
                document = new EPSendDocument(callerRecord);
                tempFileName = WinAPI::getTempFilename(WinAPI::getTempPath(), 'DAX');
                document.parmOriginal(true);
                document.parmFileName(tempFileName);
                // Make document will run the report and send it to a PDF file with
                // the path specified in tempFileName
                document.makeDocument();
                fileName = document.parmDocumentTitle();
                // remove all ';' from the filename. These are treated as delimiters by Ie
                fileName = strReplace(fileName, ';', '_');
                emptyReport = (WinAPI::fileSize(document.parmFileName()) == 0);
                response.clear();
                response.contentType('application/Octet-Stream');
                binData = new BinData();
                if (emptyReport)
                {
                    response.addHeader('Content-Disposition', 'attachment;filename="' + fileName + #txt + '"');
                    response.writeTxt(strfmt([EMAIL="'@SYS58533'"]'@SYS58533'[/EMAIL], fileName));
                }
                else
                {
                    response.addHeader('Content-Disposition', 'attachment;filename="' + fileName + #pdf + '"');
                    // Loop over the stored file and chunk it down to the client
                    fileOffset = 0;
                    while(true)
                    {
                        // BP Deviation Documented
                        if (!binData.loadFile(tempFileName, fileOffset, #BUFFER_SIZE))
                        {
                            break;
                        }
                        fileOffset += #BUFFER_SIZE;
                        response.binaryWrite(binData.getVariant());
                    }
                }
                binData = null;
                WinAPI::deleteFile(tempFileName);
            }
        }
    }
}
__________________
Axapta 3.0 sp 5 Oracle
Диплом Интернет-Университета Информационных Технологий: Основы бухгалтерского учета
Я могу взорвать вам мозг!!!
Старый 10.08.2012, 10:51   #8  
pedrozzz is offline
pedrozzz
Молодой, подающий надежды
Аватар для pedrozzz
MCBMSS
Лучший по профессии 2015
 
164 / 218 (8) ++++++
Регистрация: 18.02.2010
Адрес: Краснодар
Цитата:
Сообщение от AlexeyVS Посмотреть сообщение
X++:
    response.clear();
    response.contentType('application/Octet-Stream');
application/Octet-Stream предлагает только скачать файл пользователю, на мой взгляд, лучше предложить пользователю на выбор скачать или сразу открыть файл в программе. Я делал свитч по расширениям файлов и использовал соответствующие MIME типы. Для файлов Excel 2007, например, это будет выглядеть примерно так:

X++:
    switch (file.Extension.ToLower())
    {
        case "xlsx":
            HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            break;
        default:
            HttpContext.Current.Response.ContentType = "application/octet-stream";
            break;
    }
Тут What are the Microsoft Office MIME Types можно посмотреть другие MIME типы для офисных документов.
За это сообщение автора поблагодарили: gl00mie (2).
Теги
ax2009, ax2012, enterprise portal, mime types, законченный пример

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
AX 2012 EP. Повторный вызов Load AlexeyVS DAX: Программирование 0 04.07.2012 13:04
dynamics-community.at: Dynamics AX 2012 Trainings Blog bot DAX auf Deutsch 0 19.06.2012 18:11
AX 2012 EP deployment HTTP error 401: Unauthorised offenmeier DAX: Программирование 2 25.10.2011 14:05
dynamics-ax: Microsoft Dynamics AX 2012 Excel Add-in Blog bot DAX Blogs 0 08.06.2011 08:12
dynamics-ax: Microsoft Dynamics AX 2012 and the importance of PowerPivot Blog bot DAX Blogs 0 17.02.2011 21:11

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:19.