Как выделить метку на точечной диаграмме, используя альтаир?

Введение

Вы можете получить все через ExternalContext . В JSF 1.x вы можете получить исходный HttpServletResponse объект с помощью ExternalContext#getResponse() . В JSF 2.x вы можете использовать кучу новых методов делегатов, таких как ExternalContext#getResponseOutputStream() , без необходимости захватывать HttpServletResponse из-под кожухов JSF.

В ответе вы должны установить заголовок Content-Type, чтобы клиент знал, какое приложение следует связать с предоставленным файлом. И вы должны установить заголовок Content-Length, чтобы клиент мог вычислить ход загрузки, иначе он будет неизвестен. И вы должны установить заголовок Content-Disposition на attachment, если вы хотите диалог Сохранить как , иначе клиент попытается отобразить его в строке. Наконец, просто напишите содержимое файла в выходной поток ответа.

Наиболее важной частью является вызов FacesContext#responseComplete() , чтобы сообщить JSF, что он не должен выполнять навигацию и визуализацию после того, как вы записывает файл в ответ, иначе конец ответа будет загрязнен содержимым HTML на странице или более старыми версиями JSF, вы получите IllegalStateException с сообщением типа getoutputstream() has already been called for this response, когда реализация JSF вызывает getWriter() для отображения HTML.

Общий пример JSF 2.x

public void download() throws IOException {
    FacesContext fc = FacesContext.getCurrentInstance();
    ExternalContext ec = fc.getExternalContext();

    ec.responseReset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
    ec.setResponseContentType(contentType); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ExternalContext#getMimeType() for auto-detection based on filename.
    ec.setResponseContentLength(contentLength); // Set it with the file size. This header is optional. It will work if it's omitted, but the download progress will be unknown.
    ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // The Save As popup magic is done here. You can give it any file name you want, this only won't work in MSIE, it will use current request URL as file name instead.

    OutputStream output = ec.getResponseOutputStream();
    // Now you can write the InputStream of the file to the above OutputStream the usual way.
    // ...

    fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}

Общий JSF 1.x пример

public void download() throws IOException {
    FacesContext fc = FacesContext.getCurrentInstance();
    HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();

    response.reset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
    response.setContentType(contentType); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ServletContext#getMimeType() for auto-detection based on filename.
    response.setContentLength(contentLength); // Set it with the file size. This header is optional. It will work if it's omitted, but the download progress will be unknown.
    response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // The Save As popup magic is done here. You can give it any file name you want, this only won't work in MSIE, it will use current request URL as file name instead.

    OutputStream output = response.getOutputStream();
    // Now you can write the InputStream of the file to the above OutputStream the usual way.
    // ...

    fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}

Пример обычного статического файла

Если вам нужно передать статический файл из локальной файловой системы на диске, замените код следующим образом:

File file = new File("/path/to/file.ext");
String fileName = file.getName();
String contentType = ec.getMimeType(fileName); // JSF 1.x: ((ServletContext) ec.getContext()).getMimeType(fileName);
int contentLength = (int) file.length();

// ...

Files.copy(file.toPath(), output);

Пример общего динамического файла

В если вам нужно передать динамически сгенерированный файл, например PDF или XLS, а затем просто предоставить output там, где используемый API ожидает OutputStream.

Например iText PDF:

String fileName = "dynamic.pdf";
String contentType = "application/pdf";

// ...

Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, output);
document.open();
// Build PDF content here.
document.close();

Например. Apache POI HSSF:

String fileName = "dynamic.xls";
String contentType = "application/vnd.ms-excel";

// ...

HSSFWorkbook workbook = new HSSFWorkbook();
// Build XLS content here.
workbook.write(output);
workbook.close();

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

Отключить ajax!

Вы только необходимо убедиться, что метод действия не вызывается с помощью запроса ajax, но он вызван обычным запросом при срабатывании и . Запросы Ajax обрабатываются JavaScript, который, в свою очередь, по соображениям безопасности не имеет средств для принудительного диалога Save As с содержимым ответа ajax.

повторное использование, например PrimeFaces , то вам нужно убедиться, что вы явно отключите ajax через атрибут ajax="false". Если вы используете ICEfaces, вам нужно вставить в компонент команды.

Утилита

Если вы используете служебную библиотеку JSF OmniFaces , вы можете использовать один из трех удобных методов Faces#sendFile() , принимающих либо File, либо InputStream, либо byte[], и указав, должен ли файл загружаться как вложение (true) или inline (false).

public void download() throws IOException {
    Faces.sendFile(file, true);
}

Да, этот код завершен как есть. Вам не нужно вызывать responseComplete() и так далее. Этот метод также правильно обрабатывает заголовки IE и имена файлов UTF-8. Здесь вы можете найти исходный код .

1
задан Itay Livni 3 March 2019 в 01:51
поделиться

1 ответ

Это можно сделать, наложив две диаграммы, содержащие данные, которые вы хотите отобразить. Вот пример с некоторыми данными, сгенерированными scikit-learn, так как вы не предоставили никаких примеров:

import altair as alt
import pandas as pd
from sklearn.datasets import make_blobs

X, labels = make_blobs(20, random_state=1)
points = pd.DataFrame({
    'x': X[:, 0],
    'y': X[:, 1],
    'labels': labels
})
centers = points.groupby('labels').mean()
data = pd.concat([points , centers.reset_index()])

chart1 = alt.Chart(data).mark_point(filled=True, size=150).encode(
    x='x',
    y='y',
    color='labels:N'
)

chart2 = alt.Chart(centers).mark_point(filled=True, size=50).encode(
    x='x',
    y='y',
    color=alt.value('black')
)

chart1 + chart2

enter image description here

0
ответ дан Itay Livni 3 March 2019 в 01:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: