I am still new to Grails. I have an app that has a file upload. I have added this to the controller
def upload = {
def f = request.getFile('myFile')
if(!f.empty) {
f.transferTo( new File("${f.name}") )
response.sendError(200,'Done');
} else {
flash.message = 'file cannot be empty'
render(view:'uploadForm')
}
}
and this is in _forms.gsp
<div class="fieldcontain ${hasErrors(bean: reportInstance, field: 'myFile', 'error')} ">
<label for="myFile">
<g:uploadForm action="upload">
<input type="file" name="myFile"/>
<input type= "submit" value="Upload"/>
</g:uploadForm>
</label>
When I use a g:link to try to retrieve the upload I get redirected and there is nothing displayed
Any advice would be greatly appreciated
g:link I am using
<g:link controller ="Report"
action="listByUserCompany"
>Show first ten ordered by Title</g:link>
class UploadController {
def index() { }
def fileupload () {
def f = request.getFile('myFile')
if(!f.empty) {
f.transferTo( new File("${f.name}") )
render(view:'upload')
}
else {
flash.message = 'file cannot be empty'
render(view:'upload')
}
}
}
<body>
<g:uploadForm name="myUpload" action="fileupload" controller="upload">
<input type="file" name="myFile" />
<input type= "submit" value="Upload"/>
</g:uploadForm>
</body>
i used the above code in my controller and gsp and i made a view named upload in view->upload->upload.gsp .My file uploaded success fully in the root directory of the project itself with name myfile
Related
I'm trying to create an app that uses Spring security core 2.0 and I'm trying to create a custom registration page. I think that my problem is in my register.gsp because everytime I try to register a new user it redirects to http://localhost:8080/home/register which is completely blank. Further evidence that this might be the case is that I included several println()s in my register action that should fire off depending on where the registration fails but none of them fire off at any time. Also, there are no users created in dbconsole. Please take a look at my gsp:
<html>
<head>
<meta name="layout" content="front"/>
<title>MSK | Register</title>
<style>
...
</style>
</head>
<body>
<div class="jumbotron">
<form action="${postUrl ?: '/home/register'}" method="POST" id="registerForm" class="cssform" autocomplete="off">
<h2 class="form-signin-heading">Please register</h2>
<label for="username" class="sr-only">Username</label>
<input style="margin-bottom: 10px" type="text" id="username" class="form-control" placeholder="Username" name="${usernameParameter ?: 'j_username'}"/>
<label for="email" class="sr-only">Email</label>
<input style="margin-bottom: 10px" type="email" id="email" class="form-control" placeholder="Email" name="${emailParameter ?: 'email'}"/>
<label for="fName" class="sr-only">First Name</label>
<input style="margin-bottom: 10px" type="text" id="FName" class="form-control" placeholder="First Name" name="${fNameParameter ?: 'fName'}"/>
<label for="lName" class="sr-only">Last Name</label>
<input style="margin-bottom: 10px" type="text" id="lName" class="form-control" placeholder="Last Name" name="${lNameParameter ?: 'lName'}"/>
<label for="password" class="sr-only">Password</label>
<input style="margin-bottom: 10px" type="password" id="password" class="form-control" placeholder="Password" name="${passwordParameter ?: 'j_password'}"/>
<label for="confirmPassword" class="sr-only">Confirm Password</label>
<input style="margin-bottom: 10px" type="password" id="confirmPassword" class="form-control" placeholder="Confirm Password" name="${passwordCParameter ?: 'confirmPassword'}"/>
<g:actionSubmit style="margin-top: 20px" class="btn btn-lg btn-success btn-block" action="register" value="create"/>
<button style="margin-top: 20px" class="btn btn-lg btn-success btn-block" type="submit">Register</button>
</form>
</div>
</body>
Here is the controller and action, if that helps:
package com.mypackage
class HomeController {
def springSecurityService
//many actions
def register(){
switch(request.getMethod()){
case 'POST':
withForm {
if(params.username && params.email && params.fName && params.lName && params.password && params.confirmPassword){
if(params.password == params.confirmPassword){
def userRole = new Role(authority: 'ROLE_USER', name: 'User').save(flush: true)
def newUser = User.findByUsername(params.id)
if(!newUser){
newUser.username = params.username
newUser.email = params.email
newUser.fName = params.fName
newUser.lName = params.lName
newUser.password = params.password
newUser.enabled = true
newUser.accountExpired = false
newUser.accountLocked = false
newUser.passwordExpired = false
newUser.authorities ?: userRole
if(loginService.register(newUser)){
flash.message = "Your account has been created. Welcome " + newUser.fName
flash.message_type = 'success'
redirect(controller: 'login', action: 'auth')
}else{
flash.message = "Unable to create your account. Please try again later"
flash.message_type = 'danger'
redirect(action: 'register')
println("saving user")
}
}else{
flash.message = "That username has already been taken. Please choose a new username."
flash.message_type = 'danger'
println("checking username")
}
}else{
flash.message = "Your passwords don't match. Please try again"
flash.message_type = 'danger'
println("matching passwords")
}
}else {
flash.message = "Please fill out all required fields"
flash.message_type = 'danger'
println("filling out fields")
}
}
break;
case 'GET':
break;
println("POSTing form")
}
}
And here's the loginService's code too:
com.mypackage
//imports
#Transactional
class LoginService {
def register(newUser){
try{
def userRole = new Role(authority: 'ROLE_USER', name: 'User').save(flush: true)
newUser.save(flush: true, failOnError: true)
UserRole.create(newUser, userRole, true)
return true
}catch(all){
all.printStackTrace()
return false
}
}
}
My apologies if all the code isn't properly indented, I basically copied and pasted out of my actual project. Any help will be appreciated, thank you!
you can use the spring-security-ui plugin
use command-object, which validate the password
use resources, that means do a post to /user, that will call the save action
I have gsp with two textfield for firstname-lastname and reCaptcha. What I want is for every wrong captcha code the user's input for firstname and last name won't be erased.
snippet for controller:
***captcha_code****
if (result) {
def person = new Person(params)
person.save()
render "Success!"
} else {
flash.message = message(code: 'forgotPassword.captcha.wrong')
redirect(controller:'person', action:'form')
}
snipper for form.gsp
***captcha_code_here***
<g:form controller="person" action="save">
<label>First Name: </label>
<g:textField name="firstName"/><br/>
<label>Last Name: </label>
<g:textField name="lastName"/><br/>
<g:if test="${flash.message}">
<div class="message" role="status" style="font-size: medium;color: green;">${flash.message}</div>
</g:if>
***captcha_code_here***
<g:actionSubmit value="Save"/>
To repopulate the fields you can use the same flash scope you're using for the message. On error, add the first and last name to the flash scope, and then in your GSP use those values when they are available:
PersonController
class PersonController {
def save() {
...
if(/* recaptcha failed */) {
flash.firstName = params.firstName
flash.lastName = params.lastName
}
...
}
}
GSP
<label>First Name: </label>
<g:textField name="firstName" value="${flash.firstName ?: ''}"/><br/>
<label>Last Name: </label>
<g:textField name="lastName" value="${flash.lastName ?: ''}"/><br/>
In Controller Action, send back fields that you want to be repopulated.
how to upload file into server directory..
if my project at D:\myapp and i run with cmd d:\myapp grails run-app
when i run this app and other Computer run it and upload file..it will save ini computer server in directory D:\myapp\upload ?
i try this ini gsp.
<g:form action="list" enctype="multipart/form-data" useToken="true">
<span class="button">
<input type="file" name="filecsv"/>
<input type="button" class="upload" value="Upload"
onclick='location.href = "${createLink(url: [action: 'upload'])}"'/>
</span>
</g:form>
def upload = {
def f = request.getFile('filecsv')
if (f.empty) {
flash.message = 'file cannot be empty'
render(view: 'list')
return
}
f.transferTo(new File('C:\Users\meta\Documents\workspace-sts-2.5.2.RELEASE\wawet\wallet\uploads\file_name.csv'))
response.sendError(200, 'Done')
}
this is the error :
2014-02-03 10:43:02,706 [http-8080-2] ERROR errors.GrailsExceptionResolver - No signature of method: org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper.getFile() is applicable for argument types: (java.lang.String) values: [filecsv]
Possible solutions: getXML(), getAt(java.lang.String), getAt(java.lang.String), getLocale(), getJSON(), getHeader(java.lang.String)
groovy.lang.MissingMethodException: No signature of method: org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper.getFile() is applicable for argument types: (java.lang.String) values: [filecsv]
Possible solutions: getXML(), getAt(java.lang.String), getAt(java.lang.String), getLocale(), getJSON(), getHeader(java.lang.String)
at com.teravin.wallet.LoanAccountController$_closure12.doCall(com.teravin.wallet.LoanAccountController:308)
at com.teravin.wallet.LoanAccountController$_closure12.doCall(com.teravin.wallet.LoanAccountController)
at java.lang.Thread.run(Thread.java:744)
The destination is only a file like in Java.
def f = request.getFile('some_file')
//validate file or do something crazy hehehe
//now transfer file
File fileDest = new File("Path to some destination and file name")
f.transferTo(fileDest)
OR if you want to store it at some path relative to user home:
def homeDir = new File(System.getProperty("user.home")) //user home e.g /home/username for unix
File fileDest = new File(homeDir,"path/to/some_folder")
f.transferTo(fileDest)
UPDATE
As per why your getFile is not working, you are not submitting your form:
<g:form action="list" enctype="multipart/form-data" useToken="true">
<span class="button">
<input type="file" name="filecsv"/>
<input type="button" class="upload"
value="Upload"
onclick='location.href = "${createLink(url: [action: 'upload'])}"'/>
</span>
</g:form>
Should be:
<g:form action="upload" enctype="multipart/form-data" useToken="true">
<span class="button">
<input type="file" name="filecsv"/>
<input type="submit" class="upload" value="upload"/>
</span>
</g:form>
if you need to use javascript you should submit the form instead of adding a link to another page.
The location of your Grails app doesn't matter. You have to specify the full destination path in your controller. Here is an example
def upload() {
def f = request.getFile('filecsv')
if (f.empty) {
flash.message = 'file cannot be empty'
render(view: 'uploadForm')
return
}
f.transferTo(new File('D:\myapp\upload\file_name.txt'))
response.sendError(200, 'Done')
}
final String IMAGE_DIR = "${servletContext.getRealPath('/images')}/";
def employeeId = "dablu_photo";
def employeePicture = request.getFile("cv_");
String photoUrl ="";
if (employeePicture && !employeePicture.empty) {
if (new java.io.File(IMAGE_DIR+"/employee_photo/"+employeeId+".png")?.exists()){
FileUtils.deleteQuietly(new java.io.File(IMAGE_DIR+"/employee_photo/"+employeeId+".png"));
}
employeePicture.transferTo(new java.io.File(IMAGE_DIR+"/employee_photo/"+employeeId+".png"))
}
I'm wondering how I could save an uploaded image in grails.
The situation:
I have a gsp page with a form, containing a file upload. I tried to get the data from the fileupload, but it just won't work.
In the controller:
def file = request.getFile('fileupload')
appearanceInstance.logo = file.encodeAsBase64().toString()
In the view:
<g:form action="save" enctype="multipart/form-data">
<div class="file-upload">
<label >Choose logo</label>
<input id="fileupload" type="file" name="fileupload" onchange="handleFileSelect(this)"/>
</div><br/>
<br/>
</g:form>
Anyone who had experience with this?
this might be another way to do it, but since I adapt an in the view when an image is selected using the file upoad, can I get the image data from the in the controller?
Thanks in advance!
UPDATE:
to be clear, there are some other controls in the form, from which I get the other parameters to save.
I guess this example Simple Avatar Uploader will answer all your questions
try this i hope this will help you it works for me also see this post
Class SomeController{
def uploader(){
}
def save(){
String s=""
CommonsMultipartFile f=request.getFile('fileupload')
final String name =f.getOriginalFilename()
def fos= new FileOutputStream(new File(name))
f.getBytes().each{ fos.write(it) }
s=Base64.encode(f.getBytes())
fos.flush()
fos.close()
render 'done now refresh your source directory to see the file ${s}'
}
and the view 'uploader.gsp'
<g:form action="save" enctype="multipart/form-data">
<div class="file-upload">
<label>Choose logo</label> <input id="fileupload" type="file"
name="fileupload" />
</div>
<input type="submit" class="buttons" value="Upload" />
</g:form>
Hi try with this one .
def save = {
def requestInstance = new Request(params)
def requestNumberInstance = new RequestNumber()
if(requestInstance.validate() && requestInstance.save(flush: true)){
println "Saved successfully with ${requestInstance.picture1.length} bytes"
}
else {
println "Save failed"
}
HI. I have this classes:
class Carro {
String name
String marca
String matricula
static constraints = {
name(nullable:false, blank:false)
}
static mapping = {
version false
}
}
class CarroMovel {
String move
String rodas
String espelhos
Carro carro
static hasMany = [carros: Carro]
static constraints = {
move(nullable:false, blank:false)
}
static mapping = {
version false
}
}
And the controllers:
class CarroController{
def save2 = {
def carroInstance = new Carro()
carroInstance.name = params.name
carroInstance.marca = params.marca
carroInstance.matricula = params.matricula
if (carroInstance.save(flush: true)) {
redirect(uri:"/home.gsp")
}
else {
render(view: "/testeAdd", model: [carroInstance: carroInstance])
}
}
And the view testeAdd.gsp
<g:form controller="carro" action="save2">
<h1>Add New Carro Record</h1>
<p>Basic Information</p>
<label>Name
<span class="small">as</span>
</label>
<input type="text" name="name" value="${carroInstance?.name}" /><br>
<label>Marca
<span class="small">as</span>
</label>
<input type="text" name="marca" value="${carroInstance?.marca}" /><br
<label>Matricula
<span class="small">as</span>
</label>
<input type="text" name="matricula" value="${carroInstance?.matricula}" /><br>
<g:submitButton name="save" value="Save" id="oneone"/>
<div class="spacer"></div>
</g:form>
<g:hasErrors bean="${carroInstance}">
<div class="errors">
<g:renderErrors bean="${carroInstance}" as="list" />
</div>
</g:hasErrors>
This is working good. Now i would like to be able to data binding multiple domain classes. So, along with the current code from my gsp file, i would also like to add carroMovel occurrences all in same save2. Im not sure how to do that, specially cause class Carro will need to have an id from class carroMovel. Any help please? Thank you.
I folowed some suggestions and now the results are as follows (im not concerned about error validation yet):
def save3 = {
def carroInstance = new Carro()
def carroMovelInstance = new CarroMovel()
carroInstance.name = params.carro.name
carroInstance.marca = params.carro.marca
carroInstance.matricula = params.carro.matricula
carroMovelInstance.move = params.carroMovel.move
carroMovelInstance.rodas = params.carroMovel.rodas
carroMovelInstance.espelhos = params.carroMovel.espelhos
carroInstance.save()
carroMovelInstance.carro = carroInstance
carroMovelInstance.save()
}
<g:form controller="carro" action="save3">
<h1>Add New Conference Record</h1>
<p>Basic Information</p>
<label>Name
<span class="small">Add your name</span>
</label>
<input type="text" name="carro.name" value="${carroInstance?.name}" /><br>
<label>Marca
<span class="small">Add your name</span>
</label>
<input type="text" name="carro.marca" value="${carroInstance?.marca}" /><br
<label>Matricula
<span class="small">Add your name</span>
</label>
<input type="text" name="carro.matricula" value="${carroInstance?.matricula}" /><br>
<label>Move
<span class="small">Add your name</span>
</label>
<input type="text" name="carroMovel.move" value="${carroMovelInstance?.move}" /><br>
<label>Rodas
<span class="small">Add your name</span>
</label>
<input type="text" name="carroMovel.rodas" value="${carroMovelInstance?.rodas}" /><br>
<label>Espelho
<span class="small">Add your name</span>
</label>
<input type="text" name="carroMovel.espelho" value="${carroMovelInstance?.espelho}" /><br>
<g:submitButton name="save" value="Save" id="addConference"/>
The Carro object is saved in the database, altought, nothing happens with CarroMovel and it is not saved and i can't figure it out.
First I would change the input names to carro.name, carro.marca, carroMovel.move, ... so that they are differentiated by name.
<input type="text" name="carro.name"/><br>
<input type="text" name="carro.marca"/><br>
<input type="text" name="carroMovel.move"/><br>
This has the advantage that the binding in the controller can be done the standard Grails way, and that the correct values are entered in the form without the value attribute set.
carro.properties = params.carro
carroMovel.properties = params.carroMovel
In the controller action you can also save and link the Carro and CarroMovel instances.
carro.save()
carroMovel.carro = carro
carroMovel.save()
if(carroMovel.hasErrors(){
render(view: 'save3', model: [carro: carro, carroMovel.carroMovel])
}
If I understand your question correctly, you can give this a try.
First, edit our form to include the necessary fields for the CarroMovel class,
e.g
<label>Move
<span class="small">as</span>
</label>
<input type="text" name="move" value="${carroMovelInstance?.move}" />
then
in your save2 action,
def carroInstance = new Carro()
carroInstance.name = params.name
carroInstance.marca = params.marca
carroInstance.matricula = params.matricula
def carroMovelInstance = new CarroMovel()
carroMovelInstance.name = params.move
carroMovelInstance.marca = params.rodasa
carroMovelInstance.matricula = params.espelhos
carroMovelInstance.carro = carroInstance
Since Carro does not belong to CarroMovel saving a carroMovelInstance will not cascade to the carroInstance, therefore you will need to save each instance individually before saving its owning instance.
carroMovelInstance.carro.save()
if (carroMovelInstance.save(flush: true)) {
redirect(uri:"/home.gsp")
}
else {
render(view: "/testeAdd", model: [carroInstance: carroInstance, carroMovelInstance:carroMovelInstance])
}
Let me know if that works out for you.
Some of the other answers may be simpler, but I've been using this technique:
http://omarello.com/2010/08/grails-one-to-many-dynamic-forms/
In order for Carro to cascade save the CarroMovel reference, CarroMovel needs belongsTo = Carro or you need to manually tell hibernate to cascade it upon save using something like this:
class CarroMovel{
static mapping = {
carro cascade: 'all'
}
}
Here's the hibernate documentation about cascading:
https://docs.jboss.org/hibernate/orm/4.0/javadocs/org/hibernate/metamodel/binding/CascadeType.html
I usually use a command object for this type of thing.
In your controller do something like this:
class CarroController {
def show = {
[cmd: new MyCommand()]
}
def save2 = { MyCommand cmd ->
def carro = cmd.carro
if (carro.save()) {
cmd.movel.carro = carro
if (cmd.movel.save()) {
redirect uri: 'home.gsp'
} else {
// show form again
render view: 'show', model:[cmd:cmd]
}
} else {
// show form again
render view: 'show', model:[cmd:cmd]
}
}
// same file or some other class file
class MyCommand {
Carro carro
CarroMovel movel
}
}
You will need to adjust your form a bit as well...
Where you have "Carro" fields reference them like this:
<input type="text" name="carro.matricula" value="${cmd.carro?.matricula}" />
Where you have the "CarroMovel" fields, like this:
<input type="text" name="movel.rodas" value="${cmd.movel?.rodas}" />
This code might not be exactly right (I didn't test it), but should get you down the correct path. Also instead of referencing the objects in the command object, you could just have the fields that you are binding, and then build the actual domain objects from them, either through a helper method (def buildCarro(){...}) or by hand in the controller method.