binary data
download
js
pdf
Технические вопросы
7.x

Скачать файл с детали "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.

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


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

[javascript]
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);
},
[/javascript]

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

[csharp]
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;
}
}
[/csharp]

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

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

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

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

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

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

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