【问题标题】:Decompress a single file from a zip folder without writing in disk从 zip 文件夹中解压缩单个文件而不写入磁盘
【发布时间】:2019-12-10 13:11:24
【问题描述】:

是否可以从 zip 文件夹中解压单个文件并返回解压后的文件而不将数据存储在服务器上?

我有一个结构未知的 zip 文件,我想开发一项服务,该服务将按需提供给定文件的内容,而无需解压整个 zip 文件,也无需写入磁盘。 所以,如果我有这样的 zip 文件

zip_folder.zip
  |  folder1
       |  file1.txt
       |  file2.png
  |  folder 2
       |  file3.jpg
       |  file4.pdf
  |  ...

所以,我希望我的服务接收文件的名称和路径,以便我可以发送文件。

例如,fileName 可能是 folder1/file1.txt

 def getFileContent(fileName: String): IBinaryContent = {
    val content: IBinaryContent = getBinaryContent(...)

    val zipInputStream: ZipInputStream = new ZipInputStream(content.getInputStream)
    val outputStream: FileOutputStream = new FileOutputStream(fileName)

    var zipEntry: ZipEntry = null
    var founded: Boolean = false
    while ({
      zipEntry = zipInputStream.getNextEntry
      Option(zipEntry).isDefined && !founded
    }) {

      if (zipEntry.getName.equals(fileName)) {

        val buffer: Array[Byte] = Array.ofDim(9000) // FIXME how to get the dimension of the array
        var length = 0

        while ({
          length = zipInputStream.read(buffer)
          length != -1
        }) {
          outputStream.write(buffer, 0, length)
        }
        outputStream.close()
        founded = true
      }
    }

    zipInputStream.close()
    outputStream /* how can I return the value? */

  }

不把内容写入磁盘怎么办?

【问题讨论】:

    标签: scala zip compression


    【解决方案1】:

    您可以使用ByteArrayOutputStream 而不是FileOutputStream 将zip 条目解压缩到内存中。然后拨打toByteArray()就可以了。


    另外请注意,从技术上讲,如果您可以通过支持 deflate 编码传输的协议(想想:HTTP(S))传输 zip 部分(通常是标准压缩),那么您甚至不需要解压缩 zip 部分在 Zip 文件中使用)。

    【讨论】:

      【解决方案2】:

      所以,基本上我做了@cbley 推荐的同样的事情。我返回了一个字节数组并定义了content-type,这样浏览器就可以发挥作用了!

      def getFileContent(fileName: String): IBinaryContent = {
          val content: IBinaryContent = getBinaryContent(...)
      
          val zipInputStream: ZipInputStream = new ZipInputStream(content.getInputStream)
          val outputStream: ByteArrayOutputStream = new ByteArrayOutputStream()
      
          var zipEntry: ZipEntry = null
          var founded: Boolean = false
          while ({
            zipEntry = zipInputStream.getNextEntry
            Option(zipEntry).isDefined && !founded
          }) {
      
            if (zipEntry.getName.equals(fileName)) {
      
              val buffer: Array[Byte] = Array.ofDim(zipEntry.getSize)
              var length = 0
      
              while ({
                length = zipInputStream.read(buffer)
                length != -1
              }) {
                outputStream.write(buffer, 0, length)
              }
              outputStream.close()
              founded = true
            }
          }
      
          zipInputStream.close()
          outputStream.toByteArray
      
        }
      
      // in my rest service
      @GET
      @Path("/content/${fileName}")
      def content(@PathVariable fileName): Response = {
          val content = getFileContent(fileName)
          Response.ok(content)
              .header("Content-type", new Tika().detect(fileName)) // I'm using Tika but it's possible to use other libraries
              .build()
      }
      

      【讨论】:

        猜你喜欢
        • 2022-01-18
        • 1970-01-01
        • 1970-01-01
        • 2022-01-15
        • 1970-01-01
        • 2016-01-22
        • 1970-01-01
        相关资源
        最近更新 更多