Всегда ли apache commons-fileupload должен записывать на диск?
Я использовал fileUpload один раз, чтобы загрузить файлы на один из наших серверов, но теперь я должен сделать что-то другое. Загружаемый файл никогда не будет записан на диск, но вместо этого его следует читать построчно и вставлять в БД - каждая строка представляет купон / скидку - это внутренняя система управления контентом, поэтому файлы никогда не будут больше чем 10 или около того линий, 100 макс.
Я попытался изменить свой рабочий код, чтобы просто использовать BufferedReader и обрабатывать его в процессе чтения, но я получаю исключение NullPointerException (хотя трассировка стека отсутствует, поэтому мне нужно поиграть с log4j, чтобы получить правильный вывод). Кто-нибудь видел пример в сети или знает, что я делаю не так?
Мой фрагмент кода:
BufferedInputStream in = null;
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
String enc = request.getCharacterEncoding();
for (FileItem item : items) {
if (item.isFormField()) {
if ("code".equalsIgnoreCase(fileItem.getFieldName()))
this.code = fileItem.getString(enc);
... // set these to local variables
} else {
in = new BufferedInputStream(new FileInputStream(item.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
insert2DB(line);
}
}
}
Нужно ли мне что-то еще делать или мне нужно сначала записать это на диск, а затем прочитать?
2 ответа
В руководстве пользователя есть немного документации о том, как это сделать:
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List /* FileItem */ items = upload.parseRequest(request);
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
InputStream uploadedStream = item.getInputStream();
// your database code goes here
uploadedStream.close();
}
Для log4j вам нужен файл свойств, структурированный следующим образом:
# Root logger option
log4j.rootLogger=DEBUG, file, us
# Direct log messages to a plaintext log
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=public_html/news.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.appender.stderr=org.apache.log4j.ConsoleAppender
log4j.appender.stderr.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1} %L - %m%n
log4j.appender.stderr.layout=org.apache.log4j.PatternLayout
... и для записи трассировки стека, в вашем блоке catch, поместите loggerInstance.error(exceptionInstance.getMessage(), exceptionInstance);
и полная трассировка стека будет зарегистрирована, предполагая, что уровень ОШИБКИ также зарегистрирован.
Ошибка, которую я получал, была:
NullPointerException: charsetName
(нет трассировки стека - я предполагаю, что мой log4j не был установлен для этого проекта apache)
В любом случае, это потому, что моя старая версия использовала apache commons-fileupload-1.0, а новая версия использовала 2.0.
В старом (который я забыл иметь код выше), он сделал это:
String enc = request.getCharacterEncoding();
for (FileItem fileItem:fileItems) {
if (fileItem.isFormField()) {
if ("code".equalsIgnoreCase(fileItem.getFieldName()))
this.code = fileItem.getString(enc);
^^^
Морковные знаки - это то, что бросало ошибку. При использовании 1.0 это всегда возвращалось бы как ненулевое значение, в 2.0 оно возвращалось как нулевое и взрывалось прямо там.
Меняя это на:
this.code = fileItem.getString();
исправил проблему