Отправьте содержимое ZIP в ответ, прежде чем завершить создание Zip
Я успешно на своей "локальной сборке" смог создать временную папку и добавить в нее файлы изображений для архивирования и загрузки пользователем. К сожалению, после развертывания на моем Test-сервере я не могу создать такую временную папку и, следовательно, не могу заархивировать и передать ее, как мне кажется, из-за ошибок разрешения. В основном я на проходе. Я не могу получить доступ к созданию папок на моем тестовом сервере, и мне нужно будет либо сохранить эту папку и файлы в моем S3-хранилище, а затем создать отсюда zipOutputStream - или - я думаю, что это может быть лучшим решением, если это возможно, это просто "на лету" отправить содержимое почтового индекса в ответ, прежде чем я завершу создание почтового индекса. Это возможно? И если так, как бы это сделать? Есть ли преимущество этого метода перед временным хранением файлов на S3 для архивирования и потоковой передачи.
Текущий код для создания папок, архивирования и потоковой передачи
def downloadZip(){
def fName = params.fName // ZipFile Name passed in 'example.zip'
def fLoc = params.fLoc //Folder Location passed in '/example'
def user = User.get( fLoc as Long ) //Get the Users files to be zipped
def urlList = []
List ownedIds
//Create a temporary directory to place files inside before zipping
new File(fLoc).mkdir()
//Dynamic Resource 'http://example.com/' -or- 'http://localhost:8080/'
def location = "${resource( dir:'/', absolute:true )}"
//Collect and Download QR-Codes image files
ownedIds = user.geolinks.collect {
//Define Url for Download
def urls = (location+"qrCode/download?u=http%3A%2F%2Fqr.ageoa.com%2F" +it.linkAddress+ "&s=150&n=" +it.linkAddress)
//Download each QR-Code
download2(urls,fLoc)
}
//ZIP the directory that was created and filled with the QR codes
String zipFileName = fName
String inputDir = fLoc
ZipOutputStream zipFile = new ZipOutputStream(new FileOutputStream(zipFileName))
new File(inputDir).eachFile() { file ->
zipFile.putNextEntry(new ZipEntry(file.getName()))
def buffer = new byte[1024]
file.withInputStream { i ->
def l = i.read(buffer)
// check whether the file is empty
if (l > 0) {
zipFile.write(buffer, 0, l)
}
}
zipFile.closeEntry()
}
zipFile.close()
//Download QR-Code Zip-File
try {
def file = new File(fName)
response.setContentType("application/octet-stream")
response.setHeader("Content-disposition", "attachment;filename=${file.getName()}")
response.outputStream << file.newInputStream() // Performing a binary stream copy
}
catch(Exception e){
e.printStackTrace()
}
//Delete Temporary Folder
def dir2 = new File(fLoc)
dir2.deleteDir()
}
//Download All QR-Codes images to folder [userID]
def download2(address, dir){
def file = new FileOutputStream(dir+"/"+address.tokenize("&n=")[-1]+".png")
if(file){
def out = new BufferedOutputStream(file)
out << new URL(address).openStream()
out.close()
}
}
1 ответ
Хорошо, это должно сделать это, дайте мне знать, если что-то из этого не имеет смысла...
// A list of things to download and add to the zip
List<URL> testList = [ 'http://cdn.sstatic.net/stackru/img/sprites.png?v=6',
'https://www.google.co.uk/images/srpr/logo4w.png' ]*.toURL()
response.setHeader( "Content-disposition", "attachment; filename=resources.zip" )
response.contentType = "application/octet-stream"
// Wrap the response stream in a zipoutputstream
new ZipOutputStream( response.outputStream ).withStream { zos ->
// Always add a root folder to zip files, not to do so is spiteful
zos.putNextEntry( new ZipEntry( "resources/" ) )
// For each URL
testList.each { res ->
// Get a name for this file in the zip
// This bit might be the tricky bit as I guess you don't know the file
// names. So instead of this you might need to check the response
// object from opening a connection to the URL. However, without a
// working example URL from you, I can't be sure :-(
String name = res.path.split( '/' )[ -1 ]
// Create a zip entry for it
zos.putNextEntry( new ZipEntry( "resources/$name" ) )
// Write the resource stream into our zip
res.withInputStream { ins ->
zos << ins
}
// Close this resource
zos.closeEntry()
}
// Close the root folder
zos.closeEntry()
}