Скачать файл с детали "FileDetail" с помощью JS

Добрый день, коллеги!

Такая ситуация, есть обычная страница редактирования (PortalKnowledgeBasePage), а на ней обычная деталь (FileDetail), я хочу сделать так что бы при открытии страницы, сразу скачивался первый попавшийся файл на детали. На рендере страницы я вызываю этот метод:

renderDownloadFile: function () {
        var esqKnowledgeBaseFile = Ext.create("Terrasoft.EntitySchemaQuery", {
                "rootSchemaName": "KnowledgeBaseFile"
        });
        esqKnowledgeBaseFile.addColumn("Id");
        esqKnowledgeBaseFile.addColumn("KnowledgeBase");
        esqKnowledgeBaseFile.addColumn("Name");
        esqKnowledgeBaseFile.addColumn("Data");
        esqKnowledgeBaseFile.filters.addItem(Terrasoft.createColumnFilterWithParameter(
                Terrasoft.ComparisonType.EQUAL, "KnowledgeBase", this.get("PrimaryColumnValue")));
        esqKnowledgeBaseFile.getEntityCollection(function(resultKnowledgeBaseFile) {
                if (resultKnowledgeBaseFile.success) {
                        var textFileAsBlob = new Blob([resultKnowledgeBaseFile.collection.getByIndex(0).get("Data")], {type:'application/pdf'});
                        var fileNameToSaveAs = resultKnowledgeBaseFile.collection.getByIndex(0).get("Name");

                        var downloadLink = document.createElement("a");
                        downloadLink.download = fileNameToSaveAs;
                        downloadLink.innerHTML = "Download File";
                        if (window.webkitURL != null) {
                                downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
                        } else {
                                downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
                                downloadLink.onclick = destroyClickedElement;
                                downloadLink.style.display = "none";
                                document.body.appendChild(downloadLink);
                        }
                        downloadLink.click();
                }
        }, this);
},

Запись берет правильно, в общем он все делает правильно, кроме одного, скачивается файл, с правильным названием, с правильным количеством страниц, а вот содержимого нет. Видимо я не правильно передаю бинарные данные в конструтор Blob, но я уже все варианты перепробовал, подскажите пожалуйста!
Спасибо.

Нравится

4 комментария

Роман, проблема заключается в том что вы передаете в Blob стринг, вследствие чего файл получает нужный размер и тип, но абсолютно неправильное содержание. Работать массивами байтов в JavaScript не самая лучшая идея. Рекомендую Вам написать свой WCF сервис, который будет принимать Id записи, обращаться к базе данных и получать byte[]. Данный массив необходимо обвернуть в Stream и вернуть из сервиса добавив необходимый mime type.

Данное решение будет более простым, надежным и применимым не только на одной странице редактирования.

"Мотков Илья" написал:Роман, проблема заключается в том что вы передаете в Blob стринг, вследствие чего файл получает нужный размер и тип, но абсолютно неправильное содержание. Работать массивами байтов в JavaScript не самая лучшая идея. Рекомендую Вам написать свой WCF сервис, который будет принимать Id записи, обращаться к базе данных и получать byte[]. Данный массив необходимо обвернуть в Stream и вернуть из сервиса добавив необходимый mime type.

Данное решение будет более простым, надежным и применимым не только на одной странице редактирования.


Сделал как вы сказали, и все ровно не получается. Теперь клиентская сторона выглядит вот так:

onGetServiceInfoClick: function(idKnowledgeBase) {
				var serviceData = {
					KnowledgeBaseID: this.get("PrimaryColumnValue")
				};
				ServiceHelper.callService("CustomConfigurationService", "GetTransformValue",
				function(response) {
					var result = response.GetTransformValueResult;
					this.renderDownloadFile(result);
				}, serviceData, this);
			},
 
			renderDownloadFile: function (data) {
				var esqKnowledgeBaseFile = Ext.create("Terrasoft.EntitySchemaQuery", {
					"rootSchemaName": "KnowledgeBaseFile"
				});
				esqKnowledgeBaseFile.addColumn("Id");
				esqKnowledgeBaseFile.addColumn("KnowledgeBase");
				esqKnowledgeBaseFile.addColumn("Name");
				esqKnowledgeBaseFile.filters.addItem(Terrasoft.createColumnFilterWithParameter(
					Terrasoft.ComparisonType.EQUAL, "KnowledgeBase", this.get("PrimaryColumnValue")));
				esqKnowledgeBaseFile.getEntityCollection(function(resultKnowledgeBaseFile) { 
					if (resultKnowledgeBaseFile.success) {
						var textFileAsBlob = new Blob([data], {type:'application/pdf'});
						var fileNameToSaveAs = resultKnowledgeBaseFile.collection.getByIndex(0).get("Name");
 
						var downloadLink = document.createElement("a");
						downloadLink.download = fileNameToSaveAs;
						downloadLink.innerHTML = "Download File";
						if (window.webkitURL != null) {
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
						} else {
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
							downloadLink.onclick = destroyClickedElement;
							downloadLink.style.display = "none";
							document.body.appendChild(downloadLink);
						}
						downloadLink.click();
					}
				}, this);
			},

А сам веб сервис вот так:

public class CustomConfigurationService
    {
        [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
        ResponseFormat = WebMessageFormat.Json)]
        public MemoryStream GetTransformValue(string KnowledgeBaseID)
        {
            var UserConnection = (UserConnection)HttpContext.Current.Session["UserConnection"];
            var KnowledgeBaseFileESQ = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "KnowledgeBaseFile");
            KnowledgeBaseFileESQ.AddAllSchemaColumns();
            var KnowledgeBaseIDFilter = KnowledgeBaseFileESQ.CreateFilterWithParameters(FilterComparisonType.Equal, "KnowledgeBase", new Guid(KnowledgeBaseID));
            KnowledgeBaseFileESQ.Filters.Add(KnowledgeBaseIDFilter);
            var KnowledgeBaseFileEnteties = KnowledgeBaseFileESQ.GetEntityCollection(UserConnection);
 
            var data = KnowledgeBaseFileEnteties[0].GetColumnValue("Data") as byte[];
            var result = new MemoryStream(data);
 
            return result;
        }
    }

Ну и в последнем методе "renderDownloadFile", параметр data вот такой

И ещё пробовал с веб сервиса передать массив байтов, и принимать его вот так:

var textFileAsBlob = new Blob(data, {type:'application/pdf'});

Все ровно ничего хорошего не получилось

Роман, данный функционал уже реализован в системе. Посмотрите в сервис FileService. К примеру для файла с страницы редактирования контактов достаточно сформировать тэг

<a target='_self' href='http://localhost:8087/0/rest/FileService/GetFile/e9eafee9-c4e4-4793-ad0a-003bd2c6a9b4/564a97fc-7290-4343-b45e-8f466e5fad5b"'></a>

Где e9eafee9-c4e4-4793-ad0a-003bd2c6a9b4 - UId объекта ContactFile, а 564a97fc-7290-4343-b45e-8f466e5fad5b - Id файла из таблицы ContactFile. UId будет проще всего скопировать напрямую с уже созданных линков на детали "Файлы и ссылки".

Показать все комментарии