09.08.2012, 12:18 | #1 |
Участник
|
AX 2012 EP. Как скачать файл. Решение.
Добрый день, товарищи!
Предлагаю вашему вниманию решение проблемы закачки файлов с портала. Это может пригодится, когда на портале формируется некий отчет, например в формате Excel, кладется в папку на сервере и его необходимо передать клиенту через браузер. Должно работать так же, как работает стандартный диалог просмотра прикрепленных файлов. Буду описывать свое решение. Конструктивная критика и предложения по улучшению механизма принимаются )) |
|
|
За это сообщение автора поблагодарили: Ganna (1). |
09.08.2012, 12:28 | #2 |
Участник
|
Итак, начинаем готовить.
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()); } } |
|
09.08.2012, 12:39 | #3 |
Участник
|
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> Как видно, при загрузке этой страницы будет происходить получение имени файла из параметров запроса и вызов созданного в п. 1 метода с передачей ему имени файла. 3. Создаем в АОТ ссылку на эту страницу. Web\Web Menu ITems\URLs Назовем ее DownloadFile. В свойстве URL пишем: _layouts/ep/downloadFile.aspx |
|
09.08.2012, 13:00 | #4 |
Участник
|
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; } Спасибо за внимание! |
|
|
За это сообщение автора поблагодарили: MikeR (5), gl00mie (5), (1). |
09.08.2012, 13:16 | #5 |
Возьми свет!!!
|
перенес в четверку. что то не то творится с разрешениями файлов.
__________________
Axapta 3.0 sp 5 Oracle Я могу взорвать вам мозг!!! |
|
09.08.2012, 14:50 | #6 |
Участник
|
Боюсь в 4ке это не будет работать (
Там используется более прозаический метод закачки файлов: X++: static void redirectFile(FileName _name) { websession().redirectURL(strfmt('%1_layouts/EP/TEMP/%2', webSession().siteUrl(), _name)); } |
|
09.08.2012, 15:59 | #7 |
Возьми свет!!!
|
Цитата:
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 |
Молодой, подающий надежды
|
Цитата:
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; } |
|
|
За это сообщение автора поблагодарили: gl00mie (2). |
Теги |
ax2009, ax2012, enterprise portal, mime types, законченный пример |
|
|