I have each user's image in my project directory like user1.jpeg, user2.jpeg and so on. But when I try to change a user image it is throughing a error. I am not understanding what to do. Here is the error as follows >>>
Cannot cast object 'org.apache.catalina.core.ApplicationHttpRequest#21740230' with class 'org.apache.catalina.core.ApplicationHttpRequest' to class 'org.springframework.web.multipart.MultipartHttpServletRequest'
And here is my update action >>>
def updateUser = {
String message = ""
MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
CommonsMultipartFile f = (CommonsMultipartFile) mpr.getFile("userPhoto")//getFile("userPhoto");
if(!f.empty) {
def user = User.get(1)
user.avatarType = f.getContentType()
if(user.save()){
def userId = user.id
String username = user.username
println(userId)
String fileName = username + "." + f.getContentType().substring(6)
new File( grailsApplication.config.images.location.toString() ).mkdirs()
f.transferTo( new File( grailsApplication.config.images.location.toString() + File.separatorChar + fileName) )
message = "Here is your updated Information >>> "
render(view: 'userInfo', model: [message: message],)
}else{
message = "Can not Update User !!!"
render(view: 'editUser', model:[message: message])
return;
}
}else {
flash.message = 'file cannot be empty'
}
}
Can anyone please help me on this please? I am using grails 2.1.0.
EDIT ::
and here is the view for edit user >>>
<div class="main">
<g:form controller="user" action="updateUser">
User Name : ${username} <br/>
Photo : <input type="file" name="userPhoto" /> <p></p>
<g:hiddenField name="userId" id="userId" value="${userId}"/>
<g:submitButton name="updateUser" value="Update" />
</g:form>
// MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
def f = request.getFile("userPhoto")//getFile("userPhoto");
I have to use <g:uploadForm /> see http://grails.org/doc/latest/guide/theWebLayer.html#uploadingFiles
Everything is fine in your code just add enctype="multipart/form-data" in the form tag, like
<g:form controller="user" action="updateUser" enctype="multipart/form-data">
...
</g:form>
and your code works.
Related
I am new in Grails. I tried for several times to upload a file. But failed. I am using grails 2.3.11 . And In my config.groovy file, I already include
grails.web.disable.multipart=true
I didn't add any dependency in BuildConfig for file uploading. I need it to solve badly. I am giving Code in below
GSP code :
<g:uploadForm action="upload" enctype="multipart/form-data" useToken="true">
<fieldset class="form">
<input type="file" name="file" />
</fieldset>
<fieldset class="buttons">
<g:submitButton name="upload" class="save" value="Upload" />
</fieldset>
</g:uploadForm>
My Controller code:
def file = request.getFile('file')
I also tried with this piece of code :
MultipartRequest multipartRequest = request as MultipartRequest
def file = multipartRequest.getFile('file')
if (file){
flash.message = "File found!!"
} else {
flash.message = "File NOT found. :-( "
}
redirect action:'list'
But each and everytime I got the same error :
groovy.lang.MissingMethodException: No signature of method:
org.apache.catalina.core.ApplicationHttpRequest.getFile()
is applicable for argument types: (java.lang.String) values: [file]
Possible solutions: getXML(), getPart(java.lang.String),
getAt(java.lang.String), getAt(java.lang.String), getLocale(), getInfo()
How can solve this problem? Is there any complete example of file uploading?
You should set grails.web.disable.multipart = false inside config.groovy. This means that you want to enable multipart requests to your server. And inside your controller:
String content = request.getContentType()
if (content.contains("multipart/form-data") || (request instanceof MultipartHttpServletRequest)) {
MultipartFile uploadedFile = request.getFile('file')
if (!uploadedFile) {
flash.message = "No attachment found for upload!"
}else{
flash.message = "File uploaded successfully."
}
} else {
flash.message = "Unable to upload file, Bad Request!")
}
I'm iterating through an uploaded CSV file within my controller with a for loop. If any of my records contain errors, I need to be able to display the entire list of errors within the GSP and not save any of the records. If no errors are present, save the entire batch of records.
I'm struggling in grails to understand how to do this. Do you iterate the CSV file twice, the first time looking for errors, the second time to handle the db commit? Do I create a list of errors and send them back as a flash.message?
My Code
def uploadFile() {
CsvToBean<EffortDetail> csvToBean = new CsvToBean<>();
Map<String, String> columnMapping = new HashMap<String, String>();
columnMapping.put("ExternalID", "alternateId");
columnMapping.put("Full Name", "fullName");
columnMapping.put("OrgKey", "orgkey");
columnMapping.put("expenseDate", "expenseDate");
columnMapping.put("projectHours", "projectHours");
columnMapping.put("totalHours", "totalHours");
HeaderColumnNameTranslateMappingStrategy<EffortDetail> strategy = new HeaderColumnNameTranslateMappingStrategy<EffortDetail>();
strategy.setType(EffortDetail.class);
strategy.setColumnMapping(columnMapping);
MultipartFile file = request.getFile('file');
if(file.empty) {
flash.message = "File cannot be empty"
} else {
List<EffortDetail> effortDetails = null;
CSVReader reader = new CSVReader(new InputStreamReader(file.getInputStream()));
effortDetails = csvToBean.parse(strategy, reader);
int count = 0;
//iterate for errors
for(EffortDetail effortDetail : effortDetails) {
println "loop 1 " + count++
def recoveryDetailInstance = recoveryDetailService.populate(effortDetail)
// Test code to try and throw a list of flash messages
flash.message = count++;
}
count = 0;
//Iterate for commit
for(EffortDetail effortDetail : effortDetails) {
println "loop 2 " + count++
def recoveryDetailInstance = recoveryDetailService.populate(effortDetail)
recoveryDetailInstance.save(flush:true,failOnError:true)
}
}
redirect (action:'upload')
}
.gsp
<div class="col-md-12">
<g:if test="${flash.message}">
<div class="message" role="status">
${flash.message}
</div>
</g:if>
<g:eachError bean="${recoveryDetailInstance}">
<li>${it}</li>
</g:eachError>
<g:uploadForm action="uploadFile">
<span class="button"> <input type="file" name="file" /> <input
type="submit" class="upload" value="upload" />
</span>
</g:uploadForm>
</div>
You need to look into transaction. Here's another Stackoverflow thread that I believe does exactly what you're looking for.
Grails - Saving multiple object, Rollback all object if one fails to save
The TLDR is to move your processing logic from the controller to a Service class method. Then combine your loop into a single loop that does both the validation and the domain save. If anything errors out you can return the list of failed domain objects after invoking the rollback.
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
How can I access the current logged in user username with springSecurity in the gsp view, or more specifically, use this value in a textfield?
This solution below doesn't work:
value="${sec.loggedInUserInfo(field:'username')}"
The following lines both work correctly in my test.
<input name="username" type="text" value="${sec.username()}" />
<input name="username" type="text" value="${sec.loggedInUserInfo(field: 'username')}" />
Error you've got might be from other place. Could you test by only use that input tag in GSP?
Custom Taglib Option to get various information about the logged in the user into the view.
ExamplNameTagLib.groovy
class ExamplNameTagLib {
static namespace = 'foo'
def springSecurityService
def currentUserProps = { attrs ->
def user = springSecurityService.getCurrentUser()
if (user) {
if (attrs.username) {
out << user.username
} else if (attrs.firstName) {
out << user.firstName
} else if (attrs.lastName) {
out << user.lastName
} else if (attrs.email) {
out << user.email
}
}
}
}
exampleViewPage.gsp
//Return username from taglib of the logged in user
<g:field type="text"
name="username"
value="${foo.currentUserProps(username: true)}" />
//Return email from taglib of the logged in user
<g:field type="email"
name="email"
value="${foo.currentUserProps(email: true)}"/>
i start to write a simple login formular. This is the code for the view:
<g:form controller="login" action="checkUsernameAndPassword">
<input type = "text"name="userNameField" value="userName"/>
<input type = "password"name="passWordField" value="passWord"/>
<input type = "submit" name="loginButton" value="Login"/>
</g:form>
this is the code for the controller:
class LoginController {
def index = {
render(view: "login")
}//endMethod Index
def checkUsernameAndPassword = {
[userName = params.userName ,passWord = params.passWord];
}//endMethod checkUsernameAndPassword
}
as you can see, it doesnt do anything yet, i just wanted to print the values on the screen, however i get a 404 message (i run the file on local host)
The requested resource (/projectName/hello/checkUsernameAndPassword) is not available.
I just cant figure out why. Would be great if any of you guys have a tip for me.
beste regards,
Daniel
Edit (Change 1):
def checkUsernameAndPassword = {
render(view: "login",model: [userName: params.userName ,passWord: params.passWord])
}//endMethod checkUsernameAndPassword
}
(Change 2)
//added this line in view
<div>Username: ${userName} Passwort: ${passWord}</div>
<g:form controller="hello" action="checkUsernameAndPassword">
means that you have HelloController with checkUsernameAndPassword action
But in your code sample you have LoginController so to get your form work, you must write:
<g:form controller="login" action="checkUsernameAndPassword">
<input type = "text" name="userNameField" value="userName"/>
<input type = "password" name="passWordField" value="passWord"/>
<input type = "submit" name="loginButton" value="Login"/>
</g:form>
P.S. In Grails world is sometimes much better to use GSP Tags instead of plain HTML because it will generate proper(in 99.99% of cases) HTML code for you.
So the best way to implement your form is:
<g:form controller="login" action="checkUsernameAndPassword">
<g:textField name="userNameField" value="userName" />
<g:passwordField name="passWordField" value="passWord" />
<g:submitButton name="loginButton" value="Login" />
</g:form>
P.S.2 Proper LoginController code(for the form described before)
class LoginController {
def index = {
render(view: "login")
}//endMethod Index
def checkUsernameAndPassword = {
[userName: params.userNameField ,passWord: params.passWordField];
}//endMethod checkUsernameAndPassword