Skip to content

Commit 7d715b9

Browse files
committed
Saving uploaded multipart file to a temporary location functional.
1 parent 2a0a680 commit 7d715b9

File tree

3 files changed

+137
-0
lines changed

3 files changed

+137
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Multi File Upload
2+
3+
A plugin for multi purpose file upload functionality.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.wizpanda.file
2+
3+
import grails.util.Holders
4+
5+
/**
6+
* Endpoint for uploading file(s) to a temporary location. Used for AJAX based file upload.
7+
*
8+
* @author Shashank Agrawal
9+
* @since 0.0.1
10+
*/
11+
class UploadController {
12+
13+
static allowedMethods = [index: "POST"]
14+
static responseFormats = ["json"]
15+
static scope = "singleton"
16+
17+
FileUploadService fileUploadService
18+
19+
/**
20+
* This endpoint accepts the file in binary form, uploaded by the AJAX based application.
21+
*
22+
* @example
23+
*
24+
* When single file is uploaded:
25+
* <pre>
26+
* params.file = (a single CommonsMultipartFile)
27+
* </pre>
28+
*
29+
* Then, the response should be:
30+
* <pre>
31+
* {
32+
* filepath: "./temp/my-avatar.png",
33+
* filename: "my-avatar.png"
34+
* }
35+
* </pre>
36+
*
37+
* Note: By default this endpoint is blocked to allow upload. You need to set following to your config in order
38+
* to allow uploading files using this endpoint:
39+
*
40+
* <pre>
41+
* wizpanda.plugins.kernel.allow.file.upload = true
42+
* </pre>
43+
*
44+
* This is done because if you install this plugin and forget to protect this endpoint then someone may bloat
45+
* your server by uploading junk files.
46+
*/
47+
def index() {
48+
if (!Holders.getFlatConfig()["wizpanda.plugins.kernel.allow.file.upload"]) {
49+
log.warn "App is not allowing to upload files"
50+
return
51+
}
52+
53+
log.debug "Temporary upload with $params"
54+
55+
File file = fileUploadService.saveUploadedFile(params.file)
56+
Map result = [filepath: file.getPath(), filename: file.getName()]
57+
58+
// Work around for IE
59+
response.contentType = "text/plain"
60+
respond(result)
61+
}
62+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.wizpanda.file
2+
3+
import org.springframework.context.MessageSource
4+
import org.springframework.web.multipart.commons.CommonsMultipartFile
5+
6+
import java.nio.file.Files
7+
8+
class FileUploadService {
9+
10+
MessageSource messageSource
11+
12+
/**
13+
* Save the uploaded multipart file to a temporary location.
14+
*
15+
* @param multipartFile
16+
* @return Saved file with a metaclass method "getOriginalFilename" to get the actual uploaded file name
17+
* @throws FileNotFoundException
18+
* @throws IOException
19+
*/
20+
File saveUploadedFile(CommonsMultipartFile multipartFile) throws FileNotFoundException, IOException {
21+
if (!multipartFile || multipartFile.isEmpty()) {
22+
log.debug "Received file is either empty or does not exists"
23+
throw new FileNotFoundException(messageSource.getMessage("kernel.uploaded.file.empty", null, null))
24+
}
25+
26+
27+
InputStream inputStream
28+
FileOutputStream fileOutputStream
29+
30+
byte[] fileRead = new byte[1024]
31+
32+
try {
33+
String originalFilename = multipartFile.getOriginalFilename()
34+
35+
log.debug "Uploaded file's name [$originalFilename]"
36+
37+
// Remove special characters other than "a-z" "A-Z" "0-9" "." "-" or "_"
38+
String fileName = originalFilename.replaceAll("[^a-zA-Z0-9//._-]+", "").toLowerCase()
39+
40+
File temporaryDirectory = Files.createTempDirectory(null).toFile()
41+
File temporaryFile = new File(temporaryDirectory, fileName)
42+
43+
log.debug "File [$fileName] will be saved in [${temporaryDirectory.absolutePath}]"
44+
45+
inputStream = multipartFile.getInputStream()
46+
fileOutputStream = new FileOutputStream(temporaryFile)
47+
48+
int i = inputStream.read(fileRead)
49+
50+
while (i != -1) {
51+
fileOutputStream.write(fileRead, 0, i)
52+
i = inputStream.read(fileRead)
53+
}
54+
55+
// A dynamic method to get the original name of the file which was received
56+
temporaryFile.metaClass.getOriginalFilename = { ->
57+
return originalFilename
58+
}
59+
60+
return temporaryFile
61+
} catch (FileNotFoundException e) {
62+
log.error "Problem saving file", e
63+
throw e
64+
} catch (IOException e) {
65+
log.error "Exception saving file", e
66+
throw e
67+
} finally {
68+
fileOutputStream?.close()
69+
inputStream?.close()
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)