JSP генерирует электронную таблицу Excel (XLS) для загрузки - PullRequest
5 голосов
/ 25 января 2009

У меня есть это приложение, которое я разрабатываю в JSP, и я хочу экспортировать некоторые данные из базы данных в формате XLS (формат MS Excel).

Возможно ли в tomcat просто написать файл, как если бы это было обычное приложение Java, а затем сгенерировать ссылку на этот файл? Или мне нужно использовать конкретный API для этого?

Будут ли у меня проблемы с разрешением при этом?

Ответы [ 6 ]

9 голосов
/ 28 января 2010

Не используйте простые таблицы HTML с типом содержимого application/vnd.ms-excel. Тогда вы в основном обманываете Excel неправильным типом контента, который может вызвать сбой и / или предупреждения в последних версиях Excel. Он также испортит исходный HTML-код при редактировании и сохранении его в Excel. Только не делай этого.

CSV, в свою очередь, является стандартным форматом, который без каких-либо проблем пользуется поддержкой по умолчанию из Excel и на самом деле прост в создании и эффективен при использовании памяти. Хотя есть библиотеки, на самом деле вы также можете легко написать одну менее чем в 20 строк (забавно для тех, кто не может устоять). Вам просто нужно придерживаться спецификации RFC 4180 , которая в основном содержит только 3 правила:

  1. Поля разделены запятой.
  2. Если в поле встречается запятая, то поле должно быть заключено в двойные кавычки.
  3. Если в поле встречается двойная кавычка, то поле должно быть окружено двойными кавычками, а двойная кавычка внутри поля должна быть экранирована другой двойной кавычкой.

Вот начальный пример:

public static <T> void writeCsv (List<List<T>> csv, char separator, OutputStream output) throws IOException {
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, "UTF-8"));
    for (List<T> row : csv) {
        for (Iterator<T> iter = row.iterator(); iter.hasNext();) {
            String field = String.valueOf(iter.next()).replace("\"", "\"\"");
            if (field.indexOf(separator) > -1 || field.indexOf('"') > -1) {
                field = '"' + field + '"';
            }
            writer.append(field);
            if (iter.hasNext()) {
                writer.append(separator);
            }
        }
        writer.newLine();
    }
    writer.flush();
}

Вот пример, как вы могли бы использовать его:

public static void main(String[] args) throws IOException {
    List<List<String>> csv = new ArrayList<List<String>>();
    csv.add(Arrays.asList("field1", "field2", "field3"));
    csv.add(Arrays.asList("field1,", "field2", "fie\"ld3"));
    csv.add(Arrays.asList("\"field1\"", ",field2,", ",\",\",\""));
    writeCsv(csv, ',', System.out);
}

А внутри сервлета (да, сервлет, не используйте для этого JSP!), Вы можете сделать:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String filename = request.getPathInfo().substring(1);
    List<List<Object>> csv = someDAO().findCsvContentFor(filename);
    response.setHeader("content-type", "text/csv");
    response.setHeader("content-disposition", "attachment;filename=\"" + filename + "\"");
    writeCsv(csv, ';', response.getOutputStream());
}

Отобразите этот сервлет на что-то вроде /csv/* и вызовите его как-то вроде http://example.com/context/csv/filename.csv. Вот и все.

Обратите внимание, что я добавил возможность указывать символ разделителя отдельно, поскольку он может зависеть от используемой локали, будет ли Excel принимать запятую , или точку с запятой ; в качестве разделителя полей CSV. Обратите внимание, что я также добавил имя файла в URL pathinfo, потому что определенный веб-браузер, разработанный командой из Редмонда, в противном случае не сохранил бы загрузку с правильным именем файла.

9 голосов
/ 25 января 2009

В то время как вы можете использовать полноценную библиотеку, такую ​​как JExcelAPI , Excel также будет читать таблицы CSV и обычного HTML, если для MIME-типа ответа установлено что-то вроде «application / vnd.ms-excel».

В зависимости от сложности электронной таблицы CSV или HTML могут выполнить эту работу без сторонней библиотеки.

3 голосов
/ 25 января 2009

Вам, вероятно, понадобится библиотека для работы с файлами Excel, например JExcelAPI ("jxl") или POI . Я больше знаком с jxl, и он, конечно, может писать файлы. Вы можете генерировать их и хранить их, предоставляя им URL, но я бы не стал. Сгенерированные файлы являются болью. Они добавляют усложнение в форме на параллелизм, процессы очистки и т. Д.

Если вы можете сгенерировать файл на лету и передать его клиенту через стандартные механизмы сервлетов.

Если он генерируется много раз, может быть, или генерация стоит дорого, вы можете каким-то образом кэшировать результат, но я был бы более склонен хранить его в памяти, чем в виде файла. Я бы, конечно, избежал, если можно, ссылки на сгенерированный файл по URL. Если вы перейдете через сервлет, это позволит вам позже изменить свою реализацию. Это та же концепция инкапсуляции, что и в OO dsign.

1 голос
/ 18 мая 2012

POI или JExcel - хорошие API. Лично мне нравится больше POI, плюс POI постоянно обновляется. Кроме того, на сайте есть больше ресурсов о POI, чем JExcel, если у вас есть какие-либо вопросы Тем не менее, любой из этих двух делает большую работу.

0 голосов
/ 07 июля 2015
  try {
            String absoluteDiskPath =  test.xls";
            File f = new File(absoluteDiskPath);
            response.setContentType("application/xlsx");
            response.setHeader("Content-Disposition", "attachment; filename=" + absoluteDiskPath);
            String name = f.getName().substring(f.getName().lastIndexOf("/") + 1, f.getName().length());
            InputStream in = new FileInputStream(f);
            out.clear(); //clear outputStream prevent illegalStateException write binary data to outputStream
            ServletOutputStream outs = response.getOutputStream();
            int bit = 256;
            int i = 0;
            try {
                while ((bit) >= 0) {
                    bit = in.read();
                    outs.write(bit);
                }
                outs.flush();
                outs.close();
                in.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            } finally {
                try {
                    if(outs != null)
                        outs.close(); 
                    if(in != null)
                        in.close(); 
                }catch (Exception ioe2) {
                    ioe2.printStackTrace(); 
                }
            }
    } catch (Exception ex) {
        ex.printStackTrace();

    }
0 голосов
/ 25 января 2009

возможно, вам следует рассмотреть возможность использования какого-либо инструмента отчетности с возможностью экспорта файлов в формат XLS. я предлагаю JasperReports

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...