Skip to content

Commit 1a819d9

Browse files
Added option to clone stored file.
1 parent 7064b99 commit 1a819d9

File tree

4 files changed

+85
-4
lines changed

4 files changed

+85
-4
lines changed

grails-app/domain/com/wizpanda/file/StoredFile.groovy

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,22 @@ class StoredFile {
1212
Date uploadedOn = new Date()
1313
Map meta = [:]
1414

15-
void delete() {
15+
FileUploadService getFileUploadService() {
1616
FileUploadService fileUploadService = Holders.getApplicationContext()['fileUploadService']
1717

1818
if (!fileUploadService) {
1919
log.warn "FileUploadService bean not injected!"
2020
return
2121
}
2222

23-
fileUploadService.delete(this)
23+
return fileUploadService
24+
}
25+
26+
void remove() {
27+
fileUploadService?.delete(this)
28+
}
29+
30+
void cloneFile(String newGroupName) {
31+
fileUploadService?.cloneFile(this, newGroupName)
2432
}
2533
}

grails-app/services/com/wizpanda/file/FileUploadService.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ class FileUploadService {
3232
services.get(file.groupName).instance().delete(file)
3333
}
3434

35+
void cloneFile(StoredFile file, String newGroupName) {
36+
if (!file) {
37+
log.warn 'StoredFile cannot be null.'
38+
return
39+
}
40+
41+
if (!newGroupName) {
42+
log.warn 'New Group Name cannot be null.'
43+
return
44+
}
45+
46+
services.get(newGroupName).instance().cloneStoredFile(file, newGroupName)
47+
}
48+
3549
@PostConstruct
3650
void verifyConfig() {
3751
//log.debug "Verifying all service"

src/main/groovy/com/wizpanda/file/api/AmazonS3Api.groovy

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.wizpanda.file.api
22

3+
import com.wizpanda.file.ConfigHelper
34
import com.wizpanda.file.StoredFile
45
import com.wizpanda.file.service.AmazonS3UploaderService
56
import grails.util.Environment
@@ -9,7 +10,10 @@ import org.jclouds.ContextBuilder
910
import org.jclouds.aws.s3.AWSS3Client
1011
import org.jclouds.blobstore.BlobStore
1112
import org.jclouds.blobstore.BlobStoreContext
13+
import org.jclouds.http.HttpResponseException
14+
import org.jclouds.s3.domain.CannedAccessPolicy
1215
import org.jclouds.s3.domain.internal.MutableObjectMetadataImpl
16+
import org.jclouds.s3.options.CopyObjectOptions
1317

1418
import javax.activation.MimetypesFileTypeMap
1519

@@ -57,6 +61,15 @@ abstract class AmazonS3Api extends AbstractStorageApi {
5761
return name + "." + extension
5862
}
5963

64+
@Override
65+
String getFileName(StoredFile file) {
66+
String name = UUID.randomUUID().toString()
67+
String originalFileName = file.originalName
68+
String extension = GrailsStringUtils.substringAfterLast(originalFileName, ".")
69+
70+
return name + "." + extension
71+
}
72+
6073
String getContainerName() {
6174
String name = service.container
6275
if (Environment.current != Environment.PRODUCTION) {
@@ -85,13 +98,54 @@ abstract class AmazonS3Api extends AbstractStorageApi {
8598
this.authenticate()
8699

87100
if (!client.objectExists(container, fileName)) {
88-
log.warn "File not present in the S3 bucket."
101+
log.warn "File not present in the S3 bucket, deleting the Stored file instance."
102+
103+
file.delete()
104+
this.close()
105+
89106
return
90107
}
91108

92109
client.deleteObject(container, fileName)
93-
file.delete(flush: true)
110+
file.delete()
94111

95112
this.close()
96113
}
114+
115+
@Override
116+
StoredFile cloneStoredFile(StoredFile file, String newGroupName) {
117+
StoredFile clonedFile = new StoredFile()
118+
clonedFile.originalName = file.originalName
119+
clonedFile.groupName = newGroupName
120+
clonedFile.size = file.size
121+
clonedFile.name = getFileName(file)
122+
123+
String currentContainer = ConfigHelper.getGroup(file.groupName).container ?:
124+
ConfigHelper.getFlatConfig("global.amazon.container")
125+
126+
String newContainer = getContainerName()
127+
128+
CopyObjectOptions fileOptions = new CopyObjectOptions()
129+
// For now using the same policy of original file, it gets changed to private scope if not overridden.
130+
fileOptions.overrideAcl(CannedAccessPolicy.PUBLIC_READ)
131+
132+
try {
133+
this.authenticate()
134+
client.copyObject(currentContainer, file.name, newContainer, clonedFile.name, fileOptions)
135+
clonedFile.url = client.getObject(newContainer, clonedFile.name, null).metadata.uri
136+
137+
this.gormFile = clonedFile
138+
this.gormFile.uploadedOn = new Date()
139+
140+
this.saveGORMFile()
141+
142+
log.info "Successfully cloned StoredFile: ${file} as ${this.gormFile}"
143+
144+
return this.gormFile
145+
} catch (HttpResponseException hre) {
146+
log.warn 'Could not copy StoredFile!', hre
147+
} finally {
148+
this.close()
149+
}
150+
}
97151
}

src/main/groovy/com/wizpanda/file/api/StorageApi.groovy

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ interface StorageApi {
1717

1818
String getFileName(File file)
1919

20+
String getFileName(StoredFile file)
21+
2022
StoredFile saveGORMFile() throws FileUploadException
2123

2224
/**
@@ -35,4 +37,7 @@ interface StorageApi {
3537
StoredFile save(MultipartFile multipartFile) throws FileUploadException
3638

3739
void delete(StoredFile file)
40+
41+
// Used to clone an instance of StoredFile and get the new StoredFile instance.
42+
StoredFile cloneStoredFile(StoredFile file, String newGroupName)
3843
}

0 commit comments

Comments
 (0)