2016-05-07 3 views
0

Я пытался реализовать хранилище файлов в PostgreSQL с помощью OID:Пустой файл после загрузки

public void upload() throws SQLException, GSSException 
{ 
    if (file != null) 
    { 
     try 
     { 
      InputStream inputStream = file.getInputStream(); 
      Connection conn = ds.getConnection(); 
      PreparedStatement ps = null; 
      boolean committed = false; 
      try 
      { 
       conn.setAutoCommit(false); 

       ps = conn.prepareStatement("INSERT INTO PROCEDURE_FILES (ID, PROCEDURE_ID, FILE_NAME, FILE) " 
        + " VALUES (?, ?, ?, ?)"); 
       ps.setInt(1, obj.number); 
       ps.setInt(2, obj.number); 
       ps.setString(3, file.getSubmittedFileName()); 

       ps.setBlob(4, inputStream, inputStream.available()); 

       ps.executeUpdate(); 
       ps.close(); 

       conn.commit(); 
       committed = true; 
      } 
      catch (SQLException e) 
      { 
       e.printStackTrace(); 
      } 

      finally 
      { 
       if (!committed) 
       { 
        conn.rollback(); 
       } 

       if (ps != null) 
       { 
        ps.close(); 
       } 
       conn.close(); 
      } 
     } 
     catch (IOException e) 
     { 
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Upload failed!")); 
     } 
    } 
} 

public void initFileDBData() throws SQLException, IOException 
    { 
     Connection conn = ds.getConnection(); 
     PreparedStatement ps = null; 

     try 
     { 
      conn.setAutoCommit(false); 

      ps = conn.prepareStatement("SELECT * FROM PROCEDURE_FILES WHERE ID = ?"); 

      ps.setInt(1, id); 
      ResultSet rs = ps.executeQuery(); 
      while (rs.next()) 
      { 
       String file_name = rs.getString("FILE_NAME"); 
       Blob oid = rs.getBlob("FILE"); 
       InputStream binaryStreasm = oid.getBinaryStream(); 

       FacesContext fc = FacesContext.getCurrentInstance(); 
       ExternalContext ec = fc.getExternalContext(); 

       ec.responseReset(); 
       ec.setResponseContentLength(binaryStreasm.available()); 
       ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + file_name + "\""); 

       byte[] buf; 

       buf = new byte[binaryStreasm.available()]; 
       int offset = 0; 
       int numRead = 0; 
       while ((offset < buf.length) && ((numRead = binaryStreasm.read(buf, offset, buf.length - offset)) >= 0)) 
       { 
        offset += numRead; 
       } 

       HttpServletResponse response 
        = (HttpServletResponse) FacesContext.getCurrentInstance() 
        .getExternalContext().getResponse(); 

       response.setContentType("application/octet-stream"); 
       response.setHeader("Content-Disposition", "attachment;filename=" + file_name); 
       response.getOutputStream().write(buf); 
       response.getOutputStream().flush(); 
       response.getOutputStream().close(); 
       FacesContext.getCurrentInstance().responseComplete(); 
      } 
     } 
     finally 
     { 
      if (ps != null) 
      { 
       ps.close(); 
      } 
      conn.close(); 
     } 
    } 

Но когда я пытаюсь загрузить файл, который я всегда получить файл размером 0 байт. Как я могу решить эту проблему?

Я полагаю, что я не загружаю файл надлежащим образом?

+0

Сохранение файлов в базе данных - это всегда плохая идея. – e4c5

+0

@ e4c5 Глупости. Зависит полностью от содержимого файла и приложения. Хранение содержимого файла как blob действительно является спорным во многих случаях, но, конечно, не во всех случаях. Представьте себе, например, таблицу пользователей, рецептов, мест и т. Д. С (ссылкой) на blob для изображения. CMS обычно хранит файлы в формате blob рядом с реляционной структурой данных. – Patrick

+0

@Patrick ваше заявление без основы, но это не место, чтобы спорить об этом, поэтому я буду воздерживаться. – e4c5

ответ

0

Питер, это работает для меня с PostgreSQL 9.3 и Java OpenJDK 7.

Пишущие с LargeObjectAPI:

public static void main(String[] args) throws SQLException, FileNotFoundException, IOException { 
    Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/test01", "postgres", "postgres"); 
    conn.setAutoCommit(false); 
    File file = new File("/home/user/Pictures/somePicture.jpg"); 
    FileInputStream fis = new FileInputStream(file); 
    LargeObjectManager lom = PGConnection.class.cast(conn).getLargeObjectAPI(); 
    long oid = lom.createLO(LargeObjectManager.READ | LargeObjectManager.WRITE); 
    LargeObject lob = lom.open(oid, LargeObjectManager.WRITE); 
    byte[] buffer = new byte[2048]; 
    int s = 0; 
    while ((s = fis.read(buffer, 0, buffer.length)) > 0) { 
     lob.write(buffer, 0, s); 
    } 
    lob.close(); 
    fis.close(); 

    PreparedStatement ps = conn.prepareStatement("insert into test(id, name, content) values (nextval('test_id_seq'), ?, ?)"); 
    ps.setString(1, "foto01"); 
    ps.setLong(2, oid); 
    ps.executeUpdate(); 
    ps.close(); 
    conn.commit(); 
} 

Чтение большой объект из базы данных:

public static void main(String[] args) throws SQLException, FileNotFoundException, IOException { 
     Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/test01", "postgres", "postgres"); 
     conn.setAutoCommit(false); 

     Statement stmt = conn.createStatement(); 
     ResultSet rs = stmt.executeQuery("select id, name, content from test"); 

     LargeObjectManager lom = PGConnection.class.cast(conn).getLargeObjectAPI(); 
     byte[] buffer = new byte[2048]; 
     int s = 0; 
     while(rs.next()) { 
      File file = new File("/tmp", rs.getLong("id") + "_" + rs.getString("name")); 
      FileOutputStream fos = new FileOutputStream(file); 
      LargeObject lob = lom.open(rs.getLong("content"), LargeObjectManager.READ); 
      while((s = lob.read(buffer, 0, buffer.length)) > 0) { 
       fos.write(buffer, 0, buffer.length); 
      } 
      lob.close(); 
      fos.close(); 
     } 

     conn.close(); 
    } 

Тест стол был определен как

create table test (id serial, name varchar(256), content oid); 
Смежные вопросы