Как скачать файл pdf из базы данных oracle с помощью сервлетов, не повреждая файл? - PullRequest
0 голосов
/ 11 марта 2019

У меня есть сервлет, в котором я получаю pdf-файл из базы данных oracle на основе id и записываю его в поток ответов.Но когда я пытаюсь это сделать, загруженный файл поврежден и имеет нулевой размер файла.Читатель Adobe выдает ошибку, в которой говорится, что «Adobe не удалось открыть« myfile.pdf », поскольку он либо не поддерживается типом ...».

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.sql.Blob;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;

    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.MultipartConfig;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;



    @MultipartConfig( fileSizeThreshold = 1024 * 1024,
    maxFileSize = 1024 * 1024 * 5, maxRequestSize = 1024 * 1024 * 5 * 5)

    public class DBFileDownloadServlet extends HttpServlet {


        private static final long serialVersionUID = 1L;
        // size of byte buffer to send file
        private static final int BUFFER_SIZE = 4096;   



        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

            // get file id from URL's parameters
            String course_code = request.getParameter("course_code");

            Connection conn = null; // connection to the database

            try {
                        // connects to the database
                Connection con = JDBCfile.getOracleConnection();


                // queries the database
                String sql = "SELECT * FROM course_syllabus WHERE course_code = ?";

             PreparedStatement statement = con.prepareStatement(sql);
                    statement.setString(1, course_code);

                ResultSet result = statement.executeQuery();

            if (result.next()) {
                    // gets file name and file blob data

            String fileName = result.getString("file_name");
                    Blob blob = result.getBlob("syllabus_file");
                    InputStream inputStream = blob.getBinaryStream();
                    int fileLength = inputStream.available();

                    System.out.println("fileLength = " + fileLength);

                    ServletContext context = getServletContext();

                    // sets MIME type for the file download
                    String mimeType = context.getMimeType(fileName);
                    if (mimeType == null) {        
                        mimeType = "application/octet-stream";
                    }              

                    // set content properties and header attributes for the response
                    response.setContentType(mimeType);
                    response.setContentLength(fileLength);
                    String headerKey = "Content-Disposition";
                    String headerValue = String.format("attachment; filename=\"%s\"", fileName);
                    response.setHeader(headerKey, headerValue);

                    // writes the file to the client
                    OutputStream outStream = response.getOutputStream();

                    byte[] buffer = new byte[BUFFER_SIZE];
                    int bytesRead = -1;

                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outStream.write(buffer, 0, bytesRead);
                    }

                    inputStream.close();
                    outStream.close();             
                } else {
                    // no file found
                    response.getWriter().print("File not found for the file id: " + course_code);  
                }
            }catch (SQLException ex) {
                ex.printStackTrace();
                response.getWriter().print("SQL Error: " + ex.getMessage());
            } catch (IOException ex) {
                ex.printStackTrace();
                response.getWriter().print("IO Error: " + ex.getMessage());
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                JDBCfile.cleanup(con,statement); //closes connection      
            }
        }
    }

таблица course_syllabus содержит столбцы: course_code varchar, file_name varchar,syllabus_file (blob)

все выполняется отлично, но файл, который я загружаю, имеет нулевой байт и нечего читать.Я новичок в программировании сервлетов, у кого-нибудь есть какие-либо подсказки?Пожалуйста, опубликуйте рабочее решение тоже.Заранее спасибо.

1 Ответ

0 голосов
/ 11 марта 2019

Здесь есть одна проблема:

int fileLength = inputStream.available();

available () не возвращает общее количество байтов в потоке.Он просто возвращает количество байтов, которые можно прочитать без блокировки.Из документации :

Обратите внимание, что хотя некоторые реализации InputStream будут возвращать общее количество байтов в потоке, многие не будут. Никогда не правильно использовать возвращаемое значение этого метода для выделения буфера, предназначенного для хранения всех данных в этом потоке.

Использование Blob.length () вместо:

long fileLength = blob.length();
// ...
response.setContentLengthLong(fileLength);

Другая проблема - ваша обработка ошибок.Не действуйте так, как метод удался, если он не удался.Вы хотите HTTP-вызов для возврата ошибки, если ваш метод не смог успешно получить файл.

Сначала удалите блок catch (IOException ex).Если существует IOException, вы хотите, чтобы он распространялся, поэтому HTTP-вызов не будет выполнен должным образом.

Другие два блока должны распространять свои ошибки:

} catch (SQLException ex) {
    throw new ServletException(ex);
} catch (ClassNotFoundException e) {
    throw new ServletException(e);

Аналогично, выхотите сделать больше, чем просто напечатать «Файл не найден», когда ResultSet пуст.Существует код ответа HTTP, предназначенный специально для указания того, что запрос HTTP не выполнен, поскольку запрошенный ресурс не найден:

if (result.next()) { 
    // ...
} else {
    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
    response.getWriter().print("File not found for the file id: " + course_code);  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...