2015-06-29 41 views
0

我想创建一个通用上传代码,它可以将所有数据,文本,图像,视频文件等插入blob字段,从相同的数据中检索数据。我有 认为将文件转换为字节,然后上传它,并使用类似的方法下载它将工作。 有什么比我更喜欢的是,尽管我能够使用字节方法成功下载任何格式的文件,但通过将文件转换为字节上传文件, 只能使用pdf和文本相关文档。在上传图像文件或甚至xls文件时,我观察到blob字段的字节大小比原始文件的字节大小更新(更新:不匹配)。下载后发现这些文件是不可读的。在使用字节数组插入图像,xls文件到blob时丢失字节和数据损坏

(我所遇到的过程中https://community.oracle.com/thread/1128742?tstart=0这将帮助我实现我想要的东西。但是,这将意味着我当前的代码 相当重写。我希望有一个出路在我当前的代码本身。)

我 '插入到斑点' 代码现在是:

表结构:

desc project_storage 
Name  Null Type   
---------- ---- ------------- 
PROJECT_ID  NUMBER(38)  
FILE_NAME  VARCHAR2(200) 
DOCUMENTS  BLOB   
ALIAS   VARCHAR2(50) 
FILE_TYPE  VARCHAR2(200) 

代码:

@RequestMapping(value="/insertProject.htm", method = { RequestMethod.POST}, headers="Accept=*/*") 
    public String insert(@RequestParam Map<String,Object> parameters,@RequestParam CommonsMultipartFile file,Model model,HttpServletRequest req){ 
     try 
     { 
      log.info("Datasource || attempt to insert into project storage -Start()"); 
      if(file!=null) 
      { 
       String file_type=file.getContentType(); 
       String file_name=file.getOriginalFlename(); 
       String file_storage=file.getStorageDescription(); 
       long file_size=file.getSize(); 
       System.out.println("File type is : "+file_type); 
       System.out.println("File name is :"+file_name); 
       System.out.println("File size is"+file_size); 
       System.out.println("Storage Description :"+file_storage); 
      ByteArrayOutputStream barr = new ByteArrayOutputStream(); 
       ObjectOutputStream objOstream = new ObjectOutputStream(barr); 
       objOstream.writeObject(file); 
       objOstream.flush(); 
       objOstream.close(); 
       byte[] bArray = barr.toByteArray(); 

      // byte [] bArray=file.getBytes(); 
      // InputStream inputStream = new ByteArrayInputStream(bArray); 
       //inputStream.read(); 
       Object objArray[]=new Object[]{file_name,bArray,parameters.get("alias"),file_type}; //bArray is our target. 
      int result=dbUtil.saveData("Insert into Project_Storage(Project_Id,File_Name,Documents,Alias,File_Type) values(to_number(?),?,?,?,?)", objArray); 
      model.addAttribute(result); 

      } 
     } 
     catch(Exception e){ 
      System.out.println("Exception while inserting the documents"+e.toString()); 
      e.printStackTrace(); 
     } 

     log.info("Datasource || attempt to insert new project -end()"); 
     return "admin/Result"; 
     } 

我哪里错了?当文件是xls,图像或文件时,到底是什么填充到blob字段?

编辑:尝试上载一个虚设excel文件是如下: Game.xls file

The console output is as follows : 
    [6/29/15 20:28:41:803 IST] 0000004d SystemOut  O File type is : application/octet-stream 
    [6/29/15 20:28:41:803 IST] 0000004d SystemOut  O File name is :Game.xls 
    [6/29/15 20:28:41:804 IST] 0000004d SystemOut  O File size is: 6144 //this is original size of file. 
    [6/29/15 20:28:41:804 IST] 0000004d SystemOut  O Storage Description :in memory 
    [6/29/15 20:28:41:805 IST] 0000004d SystemOut  O DBUtil || saveData || Query : Insert into Project_Storage(Project_Id,File_Name,Documents,Alias,File_Type) values(to_number(?),?,?,?,?)|| Object : [Ljava.lang.Object;@1eecbb7 
    [6/29/15 20:28:42:020 IST] 0000004d servlet  I 

下载的文件是大小6.7 KB的,并包含数据如下: enter image description here

由此可见这是数据损坏的问题。我以前认为只有部分输入数据发生。 编辑: - 正在通过表单读取文件。

<span class="btn btn-default btn-file" id="btn_upload"> 
    Browse <input type="file" name="file"></span> 
+1

我不熟悉java,但是我遇到过一次blob问题。检查是否有任何这样的答案可以帮助你:http://stackoverflow.com/questions/31030744/how-to-get-bmp-image-from-from-binary-blob-data-with-php – Clyff

+0

@Clyff,I不要认为这是一个大小/长度的限制..虽然我也是编程新手。然而,今天从你身上学到了一件新事物:-) –

+0

为什么要保存在Blob中,或者就此而言,即使在DB中,也可以在数据库中使用一个bytea并保存为字节数组。优点是处理较少。您可以通过指定atBasic注释并延迟加载来延迟加载bytea变量,因此不会总是获取文档。 –

回答

0

您正在存储一个java对象:file。检索看起来是错误的,因为您会看到Excel文件中的一些序列化对象。

由于上传数据(file)是临时性质(上传的文件应该得到处理和删除),我不认为file将包含的全部内容(不知道,但!),最好的店显式地将内容字节与元数据分开,如文件大小和类型。这将允许立即将文件内容传送给用户。这同样适用于上传:而不是提供用于存储blob的InputStream的ByteArrayOutputStream将减少服务器负载。

将元数据分开还允许有一个很好的“目录概览”。

+0

如果文件无法包含整个内容,那么无法插入相当大尺寸的pdf文件是无能为力的。尝试实施您的建议以提高性能。 –

+0

对不起,我想你应该显示阅读代码。仍然有希望,像块读取错误或类似这样的事情是微不足道的。 –

+0

也许我错过了应该发布的内容,正在通过表单读取文件。 浏览。任何与此有关的事情? –

0

我看到了问题。 这是它的工作原理。 原始文件内容= 6144字节 这包含excel/pdf/jpeg的正确头文件。

我们称之为“A”。“A”通常由两部分组成。 [“Ah”+“Ab”] = [“A”] “Ah”是头文件,告诉excel这是一个excel文档,告诉pdf阅读器这是一个pdf文档。通常是几个字节。也许3或4,也许稍微多一些。

“Ab”是身体。

尺寸( “A”)= 6144字节 尺寸( “啊” + “AB”)= 6144个字节

确定。用6114字节完成。

接下来是您存储为blob的6.7kb。 这包含更多数据。

尺寸( “斑点”)=尺寸(CommonsMultipartFile文件)= 6.7kb

这包含[文件大小,mime类型,( “啊” + “AB”),其他数据]

所以你有2个选项。

选项a:

更改存储代码并且没有更改您的检索代码。

使用byte[] bArray = barr.toByteArray();

和存储( “阿” + “AB”)

选项B: 更改检索代码和存储的代码没有变化。 当您从数据库获取数据时,将其转换为CommonsMultipartFile file,并从中使用file.getBytes并将字节的内容写入servlet输出流。

+0

嗨,看来我能够获得移动现在成为完美另一个文件夹中的文件,内容如下:“尝试{ \t \t \t \t \t文件文件2 =新的文件(‘C:\\ \\审判’+ FILE_NAME) ; \t \t \t \t \t \t file2.getParentFile()。mkdir(); \t \t \t \t \t file2.createNewFile(); \t \t \t \t \t file.transferTo(file2); \t \t \t \t \t \t \t \t \t} \t \t \t \t赶上(抛出:SecurityException E){ \t \t \t \t的System.out.println( “文件不能由于安全异常创建”); \t \t \t \t e.printStackTrace(); \t \t \t \t}' –

+1

用于下载文件的代码位于我的其他问题中:http://stackoverflow.com/questions/31054428/extract-blob-value-and-pass-to-controller-in-spring -mvc-without-using-hibernate目前它的工作非常完美,因此不打算更改此代码。所以这给我留下了一个选项a,我想我现在正在执行这个选项。谢谢你的见解:-) –