Grails AppEngine file upload using GAEVFS - google-app-engine

I'm working on Grails web application and need to upload files.
I have a form (simplified here):
<g:form action="save" method="post" enctype="multipart/form-data">
<input type="file" id="image" name="image" />
<input class="save" type="submit" value="Create" />
</g:form>
and in Controller code (I know that this should not be in controller but this is just to make it work and than will be designed better):
def save = {
GaeVFS.setRootPath( servletContext.getRealPath( "/" ) );
FileSystemManager fsManager = GaeVFS.getManager();
FileObject tmpFolder = fsManager.resolveFile( "gae://WEB-INF/upload_files" );
if ( !tmpFolder.exists() ) {
tmpFolder.createFolder();
}
//I NEED CODE HERE TO SAVE THE IMAGE IN THE BIGTABLE VIA GAEVFS
}
So I have two problems:
A. When save create button is pressed a get exception since it tries to use Apache Commons FileUpload that tries to save to file system.
How do I disable it?
Exception is:
java.lang.NoClassDefFoundError: java.rmi.server.UID is a restricted class. Please see the Google App Engine developer's guide for more details.
at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51)
at org.apache.commons.fileupload.disk.DiskFileItem.(DiskFileItem.java:103)
at org.apache.commons.fileupload.disk.DiskFileItemFactory.createItem(DiskFileItemFactory.java:196)
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:358)
B. I need the code example to save image via gaevfs
I have seen example in GaeVfsServlet but I still don't know how exactly it should look in my case. Any kind of help is welcome.
GaeVfsServlet url: http://code.google.com/p/gaevfs/source/browse/trunk/src/com/newatlanta/appengine/servlet/GaeVfsServlet.java

I came across the very same problem and I am using a grails plugin called ajaxuploader to get around the issue - the file that gets uploaded is available to your controller as an inputstream object and doesnt have to use the commons file upload API at all.
http://www.grails.org/plugin/ajax-uploader

Related

Cannot display image from backend express react

I'm having a backend server with an upload folder directly in the root.
In my backend, http://localhost:4000, I have my upload folder and I'd like to display the image that matched the url given for each element I have in my backend :
const url = "http://localhost:4000/"
{filteredDrawings && filteredDrawings.map((drawing) => (
etc...
<div className='cardimage-container'>
<Card.Img variant='top' src={`${url}/${drawing.imageLink}`} />
</div>
When checking my browner, i have src="upload/testupload.jpg" displayed as src of the image but I have nothing displayed
I wrote app.use("/upload", express.static(path.join(__dirname, "../upload"))); in my my backend app.
When I try http://localhost:4000/upload/uploadtest.jpg, I have "Cannot GET /upload/uploadtest.jpg"
Thanks in advance
Ok problem solved, the issue was the quote not being ' but `
app.use(`/upload`, express.static(`upload`));
the error you faced is because the route /upload/uploadtest.jpg is not defined well as a route in the nodejs , you should read the document based on id or other identifier and return as a binary.
as for react try {{ }} without $
in this case it should be worked without any problem

flask file download method not allowed error

flask code
#app.route('/usecase/get/excel/<heads>', methods=['GET', 'POST'])
def get_excel(heads):
headers = {"Content-Disposition": "attachment; filename=%s" % "usecase.xls"}
with open("usecase.xls", 'r') as f:
body = f.read()
return Response(response=(body, headers))
html code
<form action="/template/usecase/get/excel/" method="post">
<button type="submit" class="btn btn-info">download</button>
</form>
if click download button, error occured "Method not allowed"..
and how to download server's file? this is exactly program?
Are you matching the right route?
/template/ does not seem to be part of your routing rules unless its some root prefix. Secondly the heads attribute is not optional so you will not hit that route anyway with that request.
On a more picky note: Why are you using a POST request to fetch the data when you clearly imply that you support the GET version.

postLink generates invalid code at CakePHP 2.3

I am using CakePHP 2.3
I have two environments where I have my web application. At the testing environment with the exact same version of the application (all files are the same) I am having a problem with the Form->postLink method.
It shows this error on the Javascript console:
Uncaught TypeError: Object # has no method 'submit' users:119
onclick
Comparing the resulting HTML from both environments I can notice that the attributes name and id generated by this method are repeated more than once in the same page (which shouldn't be like that).
This is the code use to generate those post links:
foreach($users as $user){
$delete = $this->Form->postLink(__('Delete'), array('action' => 'delete', $user['user_id']), __('Are you sure you want to delete %s?', $user['user_id']));
}
This is the problematic generated HTML with repeated values for id and name as you can see:
<!-- link 1 -->
<form action="delete/1/" name="post_51e8019d095f1" id="post_51e8019d095f1" style="display:none;" method="post">
<input type="hidden" name="_method" value="POST"/>
</form>
Delete
<!-- link 2 -->
<form action="delete/2/" name="post_51e8019d095f1" id="post_51e8019d095f1" style="display:none;" method="post">
<input type="hidden" name="_method" value="POST"/>
</form>
Delete
Why is this happening?
Could it be related with the configuration of the web server somehow? I don't see another explanation for it...
Thanks.
The problem was caused by a bug in IIS 7.0.6000.16386 and the PHP function uniqid as pointed out here.
I am using a slightly different version in both environments ( IIS 7.0.6000.16386 vs IIS 7.5.7600.16385) and that was the cause of the problem.
In order to solve it I modified the file lib/Cake/View/Helper/FormHelper.php chaning the line $formName = uniqid('post_'); inside the postLink function to:
$formName = uniqid('post_', true);
That adds more entropy and as the documentation says:
If set to TRUE, uniqid() will add additional entropy (using the combined linear congruential generator) at the end of the return value, which increases the likelihood that the result will be unique.
Update
Ended up having to add one more change due to problems with javascript in forms.
I added one more line after $formName = uniqid('post_', true); so it looks like:
$formName = uniqid('post_', true);
$formName = str_replace('.', '', $formName);

For <input type="file" ...> self.request.POST[name] is just a string

Using the GAE "helloworld" example app as a base, but changing "helloworld.py" to:
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/html'
self.response.write(
"""
<form method="post">
UPLOAD: <input type="file" name="file_param"/>
<br/>
<input type="submit" name="submit_param" value="Submit">
</form>
"""
)
def post(self):
field_storage = self.request.POST["file_param"]
try:
mimetype = field_storage.type
self.response.write("Mimetype: {}".format(mimetype))
except:
self.response.write("No FieldStorage object, field_storage={}".format(field_storage))
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
Running this in Google Chrome on Mac OSX:
Click "Choose File"
Choose a file to upload
Click "Submit"
The page that comes back says:
No FieldStorage object, field_storage=<the name of the file I uploaded>
According to http://webapp-improved.appspot.com/guide/request.html#files and examples in various posts, self.request.POST[name] should be a cgi.FieldStorage object. But as this example shows, self.request.POST[name] is a string containing the filename of the uploaded file. If it were a cgi.FieldStorage object, I would expect the program to display the mimetype of the uploaded file.
I need the cgi.FieldStorage object so I can get the mimetype and of course the value, that is, the content of the file. What am I doing wrong?
By the way, switching from webapp2 to webapp (using from google.appengine.ext import webapp) made no difference. Also, running it in Safari or Firefox, it behaved the same as in Chrome.
The form's enctype must be multipart/form-data. Please add it as follows (method attribute is case-insensitive):
<form method="POST" enctype="multipart/form-data">
Also, please consider using blobstore upload, because it doesn't have size limit, you can also use Google Cloud Storage as a backend, which will give you more flexibility on ACL and sharing capability.

Generate and download file with jboss seam

I need to add an 'export' function to an existing web app using seam. The purpose is to export search results to a csv file. I have no problem generating a csv, but I do not know how the send the csv back to the user.
I do not want to store the csv on the server because that would be waisted storage space. How could I achieve this in jboss seam?
Use the Document Store Servlet provided by Seam.
Almost copying and pasting from the reference doc, declare the servlet in web.xml like this:
<servlet>
<servlet-name>Document Store Servlet</servlet-name>
<servlet-class>org.jboss.seam.document.DocumentStoreServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Document Store Servlet</servlet-name>
<url-pattern>/seam/docstore/*</url-pattern>
</servlet-mapping>
Then create a export.xhtml file with only <s:resource> tag:
<s:resource xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
data="#{myComponent.csvData}"
contentType="application/vnd.ms-excel"
fileName="#{myComponent.csvFileName}"/>
Generate link for downloading the file in your page with <s:download>:
<s:download src="/csv/export.xhtml">
<h:outputText value="Download CSV"/>
<f:param name="param1" value="somevalue"/>
<f:param name="param2" value="someOtherValue"/>
</s:download>
Finally, implement getCsvData() and getCsvFileName() methods in your component:
// could be byte[], File or InputStream
public InputStream getCsvData() {
// generate data to be downloaded
}
public String getCsvFileName() {
return "myfile.csv";
}
Note that <s:download> propagates conversation (unless you set propagation=none). If you propagate the conversation context probably you won't need to pass any parameter. For large data set it may be preferable to not propagate the conversation and pass parameter to select the data in a request scoped component.
There's a couple of ways:
1) Check the Seam docs for info on using Seam-Excel to programmatically generate your file and then write it out using a mime-type set for CSV - this is all detailed in the docs.
However, I could not get this to work in the latest version of Seam, as it requires a response object, which used to be available from the Seam context but now only returns null.
2) Code the CSV file you want as an Excel xhtml template (see the Seam docs and example projects) and simply render this as normal using an tag.
I do this regularly and it works well, bar the restriction that you cannot supply a filename.
HTH.

Resources