Skip to content

Commit d8dfd0c

Browse files
committed
Saving StoredFile functional with Amazon S3 upload.
1 parent 5ee7f41 commit d8dfd0c

File tree

8 files changed

+152
-73
lines changed

8 files changed

+152
-73
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ buildscript {
1111
}
1212
}
1313

14-
version "0.0.2"
14+
version "0.0.3"
1515
group "com.wizpanda.plugins"
1616

1717
apply plugin:"eclipse"

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ package com.wizpanda.file
33
class StoredFile {
44

55
String originalName
6-
String path
7-
6+
String name
7+
String url
8+
String groupName
9+
Long size
10+
Date uploadedOn = new Date()
11+
Map meta = [:]
812
}

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

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,64 +3,18 @@ package com.wizpanda.file
33
import com.wizpanda.file.exception.FileUploadException
44
import com.wizpanda.file.exception.InvalidFileGroupException
55
import com.wizpanda.file.service.UploaderService
6-
import org.springframework.context.MessageSource
76
import org.springframework.web.multipart.MultipartFile
87

98
import javax.annotation.PostConstruct
10-
import java.nio.file.Files
119

1210
class FileUploadService {
1311

1412
private static Map<String, UploaderService> services = [:]
1513

16-
MessageSource messageSource
17-
18-
/**
19-
* Save the uploaded multipart file in the temporary directory of the local server which will be cleaned
20-
* automatically by the system itself.
21-
*
22-
* @param multipartFile
23-
* @return Saved file in a temporary location
24-
* @throws FileNotFoundException
25-
* @throws IOException
26-
*/
27-
File saveTemporarily(MultipartFile multipartFile) throws FileNotFoundException, IllegalStateException, IOException {
28-
if (!multipartFile || multipartFile.isEmpty()) {
29-
log.debug "Received file is either empty or does not exists"
30-
31-
throw new FileNotFoundException(messageSource.getMessage("kernel.uploaded.file.empty", null, null))
32-
}
33-
34-
try {
35-
String originalFilename = multipartFile.getOriginalFilename()
36-
File temporaryDirectory = Files.createTempDirectory(null).toFile()
37-
38-
//log.debug "Uploaded file [$originalFilename] will be saved in [${temporaryDirectory.absolutePath}]"
39-
40-
File temporaryFile = new File(temporaryDirectory, originalFilename)
41-
multipartFile.transferTo(temporaryFile)
42-
43-
return temporaryFile
44-
} catch (IllegalStateException e) {
45-
log.error "Problem saving file", e
46-
throw e
47-
48-
} catch (IOException e) {
49-
log.error "Exception saving file", e
50-
throw e
51-
}
52-
}
53-
54-
File save(MultipartFile multipartFile, String groupName) throws FileUploadException {
14+
StoredFile save(MultipartFile multipartFile, String groupName) throws FileUploadException {
5515
// TODO Add check for validating group name
56-
File temporaryFile
57-
try {
58-
temporaryFile = saveTemporarily(multipartFile)
59-
} catch (FileNotFoundException | IllegalStateException | IOException e) {
60-
throw new FileUploadException(e.message)
61-
}
6216

63-
return services.get(groupName).instance().saveFile(temporaryFile)
17+
return services.get(groupName).instance().save(multipartFile)
6418
}
6519

6620
@PostConstruct
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.wizpanda.file.api
2+
3+
import com.wizpanda.file.StoredFile
4+
import com.wizpanda.file.exception.FileUploadException
5+
import com.wizpanda.file.utils.FileUtils
6+
import org.springframework.web.multipart.MultipartFile
7+
8+
abstract class AbstractStorageApi implements StorageApi {
9+
10+
File rawFile
11+
StoredFile gormFile
12+
13+
StoredFile save(MultipartFile multipartFile) throws FileUploadException {
14+
File temporaryFile
15+
try {
16+
temporaryFile = FileUtils.saveTemporarily(multipartFile)
17+
} catch (IllegalStateException | IOException e) {
18+
throw new FileUploadException(e.message)
19+
}
20+
21+
return save(temporaryFile)
22+
}
23+
24+
StoredFile save(File rawFile) throws FileUploadException {
25+
this.rawFile = rawFile
26+
this.gormFile = new StoredFile()
27+
this.gormFile.originalName = rawFile.name
28+
this.gormFile.groupName = service.groupName
29+
this.gormFile.size = rawFile.size()
30+
31+
this.validateRawFile()
32+
this.saveNativeFile()
33+
34+
return this.saveGORMFile()
35+
}
36+
37+
@Override
38+
StoredFile saveGORMFile() throws FileUploadException {
39+
this.gormFile.save()
40+
41+
if (this.gormFile.hasErrors()) {
42+
println this.gormFile.errors
43+
// TODO Delete the native file and then throw the exception
44+
throw new FileUploadException()
45+
}
46+
47+
return this.gormFile
48+
}
49+
50+
@Override
51+
void delete(StoredFile file) {
52+
deleteNativeFile(file)
53+
}
54+
}

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

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

3+
import com.wizpanda.file.StoredFile
34
import com.wizpanda.file.service.AmazonS3UploaderService
45
import grails.util.Environment
6+
import grails.util.GrailsStringUtils
57
import org.jclouds.ContextBuilder
68
import org.jclouds.aws.s3.AWSS3Client
79
import org.jclouds.blobstore.BlobStore
@@ -10,7 +12,7 @@ import org.jclouds.s3.domain.internal.MutableObjectMetadataImpl
1012

1113
import javax.activation.MimetypesFileTypeMap
1214

13-
abstract class AmazonS3Api implements StorageApi {
15+
abstract class AmazonS3Api extends AbstractStorageApi {
1416

1517
BlobStore blobStore
1618
AWSS3Client client
@@ -46,7 +48,11 @@ abstract class AmazonS3Api implements StorageApi {
4648

4749
@Override
4850
String getFileName(File file) {
49-
return UUID.randomUUID().toString()
51+
String name = UUID.randomUUID().toString()
52+
String originalFileName = file.name
53+
String extension = GrailsStringUtils.substringAfterLast(originalFileName, ".")
54+
55+
return name + "." + extension
5056
}
5157

5258
String getContainerName() {
@@ -61,4 +67,14 @@ abstract class AmazonS3Api implements StorageApi {
6167
String getDirectory() {
6268

6369
}
70+
71+
@Override
72+
void validateRawFile() {
73+
74+
}
75+
76+
@Override
77+
void deleteNativeFile(StoredFile file) {
78+
// TODO implement me
79+
}
6480
}

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

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@ package com.wizpanda.file.api
33
import com.wizpanda.file.StoredFile
44
import com.wizpanda.file.service.AmazonS3UploaderService
55
import org.jclouds.aws.s3.blobstore.options.AWSS3PutObjectOptions
6-
import org.jclouds.blobstore.domain.Blob
76
import org.jclouds.s3.domain.CannedAccessPolicy
87
import org.jclouds.s3.domain.S3Object
98
import org.jclouds.s3.domain.internal.MutableObjectMetadataImpl
109
import org.jclouds.s3.domain.internal.S3ObjectImpl
11-
import org.springframework.web.multipart.MultipartFile
1210

1311
class AmazonS3PermanentURLApi extends AmazonS3Api {
1412

@@ -17,33 +15,27 @@ class AmazonS3PermanentURLApi extends AmazonS3Api {
1715
}
1816

1917
@Override
20-
StoredFile saveFile(File file) {
21-
authenticate()
22-
upload(file)
23-
close()
18+
void saveNativeFile() {
19+
this.authenticate()
2420

25-
return null
26-
}
27-
28-
String upload(File file) {
2921
AWSS3PutObjectOptions fileOptions = new AWSS3PutObjectOptions()
3022
fileOptions.withAcl(CannedAccessPolicy.PUBLIC_READ)
3123

32-
String fileName = getFileName(file)
24+
String fileName = getFileName(this.rawFile)
25+
String containerName = getContainerName()
3326

3427
MutableObjectMetadataImpl mutableObjectMetadata = new MutableObjectMetadataImpl()
3528
mutableObjectMetadata.setKey(fileName)
36-
setContentType(mutableObjectMetadata, file)
29+
setContentType(mutableObjectMetadata, this.rawFile)
3730

3831
S3Object s3Object = new S3ObjectImpl(mutableObjectMetadata)
39-
s3Object.setPayload(file)
32+
s3Object.setPayload(this.rawFile)
33+
34+
client.putObject(containerName, s3Object, fileOptions)
4035

41-
return client.putObject(getContainerName(), s3Object, fileOptions)
42-
/*Blob blob = blobStore.blobBuilder("blob-name")
43-
.payload(file)
44-
.contentLength(file.size())
45-
.build()
36+
this.gormFile.name = fileName
37+
this.gormFile.url = client.getObject(containerName, fileName, null).metadata.uri
4638

47-
blobStore.putBlob(getContainerName(), blob)*/
39+
this.close()
4840
}
4941
}
Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,38 @@
11
package com.wizpanda.file.api
22

33
import com.wizpanda.file.StoredFile
4+
import com.wizpanda.file.exception.FileUploadException
45
import com.wizpanda.file.service.UploaderService
56
import org.springframework.web.multipart.MultipartFile
67

78
interface StorageApi {
89

910
UploaderService service
1011

11-
StoredFile saveFile(File file)
12+
void saveNativeFile()
13+
14+
void validateRawFile()
15+
16+
void deleteNativeFile(StoredFile file)
1217

1318
String getFileName(File file)
19+
20+
StoredFile saveGORMFile() throws FileUploadException
21+
22+
/**
23+
* The entry point of the Storage API instance which will accept a raw file to be saved/uploaded via an API.
24+
* @param rawFile
25+
* @return Newly saved GORM StoredFile instance
26+
*/
27+
StoredFile save(File rawFile) throws FileUploadException
28+
29+
/**
30+
* The entry point of the Storage API instance which will accept an uploaded multipart file to be saved/uploaded via
31+
* an API.
32+
* @param multipartFile
33+
* @return Newly saved GORM StoredFile instance
34+
*/
35+
StoredFile save(MultipartFile multipartFile) throws FileUploadException
36+
37+
void delete(StoredFile file)
1438
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.wizpanda.file.utils
2+
3+
import org.springframework.web.multipart.MultipartFile
4+
5+
import java.nio.file.Files
6+
7+
class FileUtils {
8+
9+
/**
10+
* Save the uploaded multipart file in the temporary directory of the local server which will be cleaned
11+
* automatically by the system itself.
12+
*
13+
* @param multipartFile
14+
* @return Saved file in a temporary location
15+
* @throws FileNotFoundException
16+
* @throws IOException
17+
*/
18+
static File saveTemporarily(MultipartFile multipartFile) throws IllegalStateException, IOException {
19+
if (!multipartFile || multipartFile.isEmpty()) {
20+
throw new FileNotFoundException("Uploaded file is empty or null")
21+
}
22+
23+
try {
24+
String originalFilename = multipartFile.getOriginalFilename()
25+
File temporaryDirectory = Files.createTempDirectory(null).toFile()
26+
27+
File temporaryFile = new File(temporaryDirectory, originalFilename)
28+
multipartFile.transferTo(temporaryFile)
29+
30+
return temporaryFile
31+
} catch (IllegalStateException | IOException e) {
32+
throw e
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)