从zip文件夹解压缩单个文件,而无需写入磁盘

时间:2019-12-10 13:11:24

标签: scala zip compression

是否可以从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? */

  }

如何在不将内容写入磁盘的情况下做到这一点?

2 个答案:

答案 0 :(得分:0)

您可以使用ByteArrayOutputStream代替FileOutputStream将zip条目解压缩到内存中。然后在其上调用toByteArray()


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

答案 1 :(得分:0)

因此,基本上我做了@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()
}
相关问题