Trying to delete a uploaded file from directory file system - grails

I have a web app that uploads files to file system and show them in a list. I am trying to delete the item with a button. I know I need to get the path of the directory file to be able to delete it and I believe this is where I am stuck:
def delete = {
def doc = Document.get(params.id)
def path = Document.get(path.id)
doc.delete(path)
redirect( action:'list' )
}
error I am getting: No such property: path for class: file_down.DocumentController Possible solutions: flash
It seems to me def path = Document.get(path.id) is wrong, in that case how do we find the path of a document ?
This is my upload method where I upload the files, assign it to a specific filesize, date, and fullPath( which is the uploaded folder)
def upload() {
def file = request.getFile('file')
if(file.empty) {
flash.message = "File cannot be empty"
} else {
def documentInstance = new Document()
documentInstance.filename = file.originalFilename
documentInstance.fullPath = grailsApplication.config.uploadFolder + documentInstance.filename
documentInstance.fileSize = file.getSize() / (1024 * 1024)
documentInstance.company = Company.findByName(params.company)
if (documentInstance.company == null) {
flash.message = "Company doesn't exist"
redirect (action: 'admin')
}
else {
file.transferTo(new File(documentInstance.fullPath))
documentInstance.save()
redirect (action:'list', params: ['company': params.company])
}
}
}

I think you have an error in this line:
def path = Document.get(path.id)
You try to get path.id from the path variable you are just declaring.
I'm pretty sure that you mean
def path = new File(doc.fullPath)
path.delete() // Remove the file from the file-system
doc.delete() // Remote the domain instance in DB
Alternative:
class Document {
// Add this to your Document domain
def beforeDelete = {
new File(fullPath).delete()
}
}
and then you could just do this in your controller:
def delete = {
def doc = Document.get(params.id)
doc.delete() // Delete the domain instance in DB
redirect( action:'list' )
}

Related

Downloading content from URL without prompting for authentication in Grails

I am working on a web app programmed in Grails. I have a page used to display a certain report and these reports can contain attachments. The attachment is stored in documentum and currently, when the user clicks on it, it is only a link to the location in documentum where the attachment is stored and prompts the user for his credentials. My app has documentum credentials stored in the configuration file therefore I want to use those rather than forcing the user to enter his own credentials. I am using RESTful services to retrieve link but I am trying to find a way to use the link to download directly to the users computer.
private def getFileInfo(def id, def subject) {
// product show view needs the following four lists to display the document information correctly
def ATRReportInstance = ATRReport.findByTrackingNumber(id)
def linkList = []
def nameList = []
def formatList = []
def idList = []
// open up a connection to the documentum server
def doc = connectToDocumentum()
if (!doc) return
def rest = doc.rest
def response = doc.response
if (response.status == 200) {
// retrieve the folder for this product (the name of this folder is the product's ID)
def rObjectId = rest.get(documentumServer + "/repositories/" + documentumfilestore + "?dql=select r_object_id from dm_folder where any r_folder_path='" + atrreportfolderpath + "/" + id + "'") {
auth authuser, authpass
}
// get the folder's ID from the folder object retrieved above
def folderObjectID
rObjectId.json.entries.each {
entry - >
folderObjectID = entry.content.properties.r_object_id
}
// get all of the documents in the product's MSDS folder using the folder ID retrieved above
def resp = rest.get(documentumServer + "/repositories/" + documentumfilestore + "?dql=select r_object_id, object_name, a_content_type, subject from cbs_document where any i_folder_id= '" + folderObjectID + "'") {
auth authuser, authpass
}
// cycle through the documents above to populate the four MSDS document information lists
def x = 0
resp.json.entries.each {
entry - >
if (entry.content.properties.subject == subject) {
// get the document's content object from the document's ID
def content = rest.get(documentumServer + "/repositories/" + documentumfilestore + "/objects/" + entry.content.properties.r_object_id + "/contents/content" + "?media-url-policy=local") {
auth authuser, authpass
}
if (entry.content.properties.r_object_id != null && ATRReportInstance.inactiveFiles != null && ATRReportInstance.inactiveFiles.contains(entry.content.properties.r_object_id.toString())) {} else {
linkList[x] = getLink(content.json.links, "enclosure")
if (linkList[x].contains("format=msg"))
linkList[x] = linkList[x].toString().substring(0, linkList[x].toString().indexOf("content-media")) + "content-media.msg"
formatList[x] = entry.content.properties.a_content_type
nameList[x] = entry.content.properties.object_name
idList[x] = entry.content.properties.r_object_id
x++
}
}
}
return [linkList: linkList, nameList: nameList, formatList: formatList, idList: idList]
} else {
// return null if documentum is unavailable
flash.message = message(code: 'error.documentum.unavailable')
return null
}
}
I'm thinking writing another function that can take in a URL and download the document to the user might work, but I can't figure how to retrieve that document within Grails.
If you want to bypass login you could either setup a SSO solution (requires some work for DCTM) or do a function as you suggest. However you should consider the licensing terms when doing this.
Here is the solution I implemented and that worked. It is a method that downloads a file in documentum using authentication credentials found in a configuration file.
def exportAttachment() {
//uses parameters from gsp file
def url = params.url
def name = params.name
def format = params.format
def extension
//find proper extension
for (s in documentumExtMap) {
if (s.value.equals(format)) {
extension = s.key
}
}
def connection = new URL(url).openConnection()
def remoteAuth = "Basic " + "${authuser}:${authpass}".bytes.encodeBase64()
connection.setRequestProperty("Authorization", remoteAuth)
def dataStream = connection.inputStream
response.setContentType("application/octet-stream")
response.setHeader('Content-disposition', 'Attachment; filename=' + name + '.' + extension)
response.outputStream << dataStream
response.outputStream.flush()
}
The method has three parameters: url, name, format.
Url is the location of the file in documentum.
Name is the name of the download client side
Format is the type of file that is being downloaded. In my case, I had to use this to get the proper extension needed for the file.

Want to Delete and Insert in same Action

I have one action in my controller that upload csv file with list of numbers.
Now the process is first I need to delete existing data from the table on certain condition then insert fresh data.
My snippet code is as follows..
Controller:
#Transactional
def uploadFile() {
if(!params?.updateExisting){
println "Going to call service to delete records"
myService.deleteNumbers()
def newList = Number.findAllByDeleted(false)
println "NEW LS:"+newList
//HERE I'm GETTING BLANK
}
def file = request.getFile("fileCsv")
file.inputStream
.splitEachLine(',') { fields ->
Number.withNewTransaction {
def number = fields[0]?.toString().replaceAll(" ","").replaceAll("-","")
Number numberInstance = new Number()
def numberExist = Number.findAllByNumberAndDeleted(number, false)
//HERE NUMBER IS STILL EXIST
if(!numberExist){
numberInstance.number = number
numberInstance.save(flush:true)
count++
}else{
println "Number exist: "+number
}
}
}
redirect(uri:'/number/list')
}
myService:
#Transactional
def deleteNumbers(){
Number.findAll().each {
it.deleted = true
it.save(flush: true)
}
}
After calling service method deleteNumbers I'm getting blank list NEW LS:[], But then def numberExist = Number.findAllByNumberAndDeleted(number, false) returns me a number means already exist.
Thanks..
Try removing Number.withNewTransaction closure. Your code should work..

commonsMultipartFile trouble

Hi I have am trying to implement a file upload in my application where the file uploaded is parsed and an entry is created in the database using that information.
def save = {
def file = request.getFile("file");
def filename = file.getOriginalFilename();
def type = filename.split('\\.');
if(!file.isEmpty()){
if(type[1] == "properties"){
redirect(action:"parsePropertyFile", params:params);
}
}
}
def parsePropertyFile = {
println "\n"
println params.file;
println "\n";
def f = params.file;
println f;
def filename = f.getOriginalFilename();
println filename;
}
when I print out f this is output:
org.springframework.web.multipart.commons.CommonsMultipartFile#29d32df9
but when I try to call getOriginalFilename() on f I get the following error:
groovy.lang.MissingMethodException: No signature of method:
java.lang.String.getOriginalFilename() is applicable for argument types: () values: []
I also printed out file from the save function and the output of that is also:
org.springframework.web.multipart.commons.CommonsMultipartFile#29d32df9
so why am I getting the error?
Instead of redirecting, can you just call your another function? Redirect will issue an http redirect with the file as param with no need.
if(type[1] == "properties") {
parsePropertyFile(file)
}
And then:
private def parsePropertyFile(def file) {
String filename = file.getOriginalFilename();
...
}
In your parsePropertyFile action you aren't getting a File object, you're getting the String from params. Just like in your save action, you need to do
def f = request.getFile('file')
println f.getOriginalFilename()

Image upload to filesystem in Grails

I'm implementing a file upload functionality to a web-app in Grails. This includes adapting existing code to allow multiple file extensions. In the code, I've implemented a boolean to verify that the file path exists, but I'm still getting a FileNotFoundException that /hubbub/images/testcommand/photo.gif (No such file or directory)
My upload code is
def rawUpload = {
def mpf = request.getFile("photo")
if (!mpf?.empty && mpf.size < 200*1024){
def type = mpf.contentType
String[] splitType = type.split("/")
boolean exists= new File("/hubbub/images/${params.userId}")
if (exists) {
mpf.transferTo(new File("/hubbub/images/${params.userId}/picture.${splitType[1]}"))
} else {
tempFile = new File("/hubbub/images/${params.userId}").mkdir()
mpf.transferTo(new File("/hubbub/images/${params.userId}/picture.${splitType[1]}"))
}
}
}
I'm getting the exception message at
if (exists) {
mpf.transferTo(new File("/hubbub/images/${params.userId}/picture.${splitType[1]}"))
}
So, why is this error happening, as I'm simply collatating an valid existing path as well as a valid filename and extension?
Why do you think that convertation of File object to Boolean returns existence of a file?
Try
File dir = new File("/hubbub/images/${params.userId}")
if (!dir.exists()) {
assert dir.mkdirs()
}
mpf.transferTo(new File(dir, "picture.${splitType[1]}"))

convert CommonsMultipartFile to file

I am using a plugin that uploads files as a CommonsMultipartFile. The upload works fine, but I am trying to use another plugin to read the files header (the mp3 header) but it will not take CommonsMultipartFile, only regular files. Is there a way to either convert the CommonsMultipartFile to a file or have some other work around. I've tried copying the file from where it gets uploaded from, but it doesn't seem to work. here is what i have so far:
if (request instanceof MultipartHttpServletRequest) {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;
CommonsMultipartFile file = (CommonsMultipartFile)multiRequest.getFile("files");
moveFile(file)
}
private moveFile(CommonsMultipartFile file){
def userId = getUserId()
def userGuid = SecUser.get(userId.id).uid
def webRootDir = servletContext.getRealPath("/")
def userDir = new File(webRootDir, "/myUsers/${userGuid}/music")
userDir.mkdirs()
file.transferTo( new File( userDir,file.originalFilename))
def myFile = new File( "/myUsers/${userGuid}/music/" + file.originalFilename)
AudioFile audioFile = AudioFileIO.read(file);
//AudioFile is expecting a file, not a CommonsMultipartFile
}
When i do this, though, i get this error:
groovy.lang.MissingMethodException: No signature of method: static org.jaudiotagger.audio.AudioFileIO.read() is applicable for argument types: (org.springframework.web.multipart.commons.CommonsMultipartFile) values: [org.springframework.web.multipart.commons.CommonsMultipartFile#10a531]
Thanks
jason
Your code copied MultiPart file to a File, but still used Multipart file for AudioFileIO.
It must be like:
private moveFile(CommonsMultipartFile file){
def userId = getUserId()
def userGuid = SecUser.get(userId.id).uid
def webRootDir = servletContext.getRealPath("/")
def userDir = new File(webRootDir, "/myUsers/${userGuid}/music")
userDir.mkdirs()
File myFile = new File( userDir,file.originalFilename)
file.transferTo(myFile)
//
// !!!!!! you have to pass myFile there
//
AudioFile audioFile = AudioFileIO.read(myFile)
}

Resources