Неполадки при генерации файла размером более 200 МБ в ZIP с использованием ByteArrayOutputStream и ZipOutputStream - PullRequest
0 голосов
/ 05 июля 2018

Мне снова нужна твоя помощь. Мое приложение пытается экспортировать файлы пользователя (настройки, процессы, стандартные файлы и т. Д.) В формате ZIP. Этот экспортированный ZIP будет использоваться позже для импорта файлов пользователя в другую систему. До сих пор я сделал следующий код:

def files = File.findAllByUser(user)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)

files.each { File it ->
   if (it.fileContent.content) {
      ZipEntry entry = new ZipEntry(user.name + "-" + it.id)
      entry.setSize(it.fileContent.content.length())

      zipOutputStream.putNextEntry(entry)
      zipOutputStream.write(it.fileContent.content.getBytes(1, it.fileContent.content.length() as int))
      zipOutputStream.closeEntry()
   } else {
      log.error("File ${it.id} has no content")
   }
}

Я сохранил файлы в формате xml, а затем в виде ZIP в каталоге пользователя, как показано в следующем коде:

ZipEntry entry = new ZipEntry("${user}.xml")
entry.setSize(xml.bytes.length)
zipOutputStream.putNextEntry(entry)
zipOutputStream.write(xml.bytes)
zipOutputStream.closeEntry()
zipOutputStream.close()

Directory backupDir = Directory.findByUserAndIsBackupDirectory(userName, true)

File savedFile = new File(user: user, name: "${userName}.zip", contentType: "application/zip", directory: backupDir).save(flush: true, failOnError: true)
FileContent savedFileContent = new FileContent(file: savedFile).save(flush: true, failOnError: true)
savedFileContent.setDataBytes(outputStream.toByteArray())

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

1 Ответ

0 голосов
/ 06 июля 2018

Разделите выходной поток, чтобы не пытаться загрузить все сразу:

byte[] buffer = new byte[16 * 1024]
File zipFile = new File("myfile.zip")
zipFile.withOutputStream { OutputStream out ->
  ZipOutputStream zipOutputStream = new ZipOutputStream(out)
  File[] fileList = <<the list of files to zip>>
  fileList.each { File file ->
    zipOutputStream.putNextEntry(new ZipEntry(file.getName()))
    def inputStream = new FileInputStream(file)
    int len
    while ((len = inputStream.read(buffer)) > 0) {
      zipOutputStream.write(buffer, 0, len)
    }
    inputStream.close()
    zipOutputStream.closeEntry()
  }
  zipOutputStream.finish()
}
...