I'm using Apache Tapestry v5.3.7 and I already use the normal Tapestry upload component in a form. For a better user experience I try now to integrate Dropzone.js in a normal Tapestry page without any form. The JavaScript integration works fine. The uploaded file data are transferred to my server with a post request and I can access the request with all of its parameters.
My question is now how can I access the binary data of the uploaded file (maybe as InputStream) to save them in my system? I already injected the http request but getInputStream returns a empty stream.
Thanks for any suggestions
/** Code snippet of page java part */
...
#Inject
protected HttpServletRequest _request;
public void onActivate (String rowId) {
String fileName=_request.getParameter("file");
try {
InputStream is=_request.getInputStream();
// if I do read from is it returns -1
// :-(
doSomeSaveStuff(is); // dummy code
}
catch(Exception e) {
e.printStackTrace();
}
}
...
Here's one way to do it:
In template:
<t:form t:id="testForm" class="dropzone">
</t:form>
In page.java
#Inject
MultipartDecoder multipartDecoder;
#Component(id = "testForm")
private Form testForm;
#Inject
RequestGlobals requestGlobals;
void onSubmitFromTestForm() throws ManagerException {
System.out.println("test form invoked");
HttpServletRequest r = requestGlobals.getHTTPServletRequest();
UploadedFile u = multipartDecoder.getFileUpload("file");
The uploaded file contains what you uploaded and you can work with it the way you want.
Note: the HttpServletRequest::getParameterMap() , told me that the handle to to the file is called file which is how I know that passing file to getFileUpload makes the decoder correctly parse the multipart/post
Related
In my code currently, I get data from the database and then I write a file out of the data. I have this kind of camel route and working solution:-
private static final String INPUT_FILE_DIRECTORY_URI = "file:" + System.getProperty("user.home")
+ "/data/cdr/?noop=false";
private static final String SFTP_SERVER = "sftp://" +System.getProperty("user.name")
+ "#sftp_server_url/data/cdr/?privateKeyFile=~/.ssh/id_rsa&passiveMode=true";
from(INPUT_FILE_DIRECTORY_URI)
.streamCaching()
.log("Sending file to local sftp")
.to(SFTP_SERVER);
I don't want to write a file in the local disk. Instead, I want to write file data directly to the SFTP server. I don't know how to do it? But I imagine it should be possible to do it. Can you tell me is it possible? If yes, how to do it?
I managed to solve this problem in another way. It is more suitable for my particular problem.
byte[] csvData = csvStringBuilder.toString().getBytes();
Routes.withProducer(producer)
.withHeader(Exchange.FILE_NAME, myCsvFile.csv)
.withBody(csvData)
.to(SFTP_SERVER).request(byte[].class);
You shouldn't use streamCaching unless you really using it. It store your file in memory, use it if you need to consume multiples times your input.
You can use Jpa component or a custom bean getting your data. Load it from database and then send it to your ftp server.
With Jpa :
#Entity
#NamedQuery(name = "data", query = "select x from Data x where x.id = 1")
public class Data { ... }
After that you can define a consumer uri like this one:
from("jpa://org.examples.Data?consumer.namedQuery=data")
.to("SFTP_SERVER");
EDIT : to convert a list to csv and send it to ftp :
from("jpa://org.examples.Data?consumer.namedQuery=data")
.marshal()
.csv()
.to("sftp://" +System.getProperty("user.name") +
"#sftp_server_url/data/cdr/myFile.csv?" +"privateKeyFile=~/.ssh/id_rsa&passiveMode=true");
See CSV component who convert a list to a csv file.
Yes it is possible :) To do this send the file inputStream in a camel DIRECT component and in the associated route make the copy to FTP. I use this case, to upload a file and directly copy it to ftp with from(directInputStreamName).to(yourFtpUri). This is an sample code :
Your service
#Service
public class FileService {
#Produce(uri = PfnumDownloadConstants.CAMEL_DIRECT_UPLOAD)
private ProducerTemplate producer;
public void sendFileToFtp(File fileToSend, String ftpDestinationUri) throws IOException {
Map<String, Object> headers = new HashMap<>();
//In this variable you can init the ftp destination uri or you can hard code it in route
headers.put("destinationUri", ftpDestinationUri);
//set filename to name your file in ftp
headers.put(Exchange.FILE_NAME_ONLY, file.getName());
InputStream targetStream = new FileInputStream(file);
//send stream as body and list of headers to direct
producer.sendBodyAndHeaders(targetStream, headers);
}
}
Your Camel route
#Component
public class FileUploadRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
//Manage camel exception in a dedicated processor
onException(Exception.class).process(exceptionProcessor).log("error :: ${exception}");
from(CAMEL_DIRECT_UPLOAD)
.log("file copy to ftp '${header.CamelFileNameOnly}' in process")
.toD("file:/mnt?fileName=${header.CamelFileNameOnly}&delete=false")
.log("copy done");
}
}
I'm using the following code to dynamically generate a download in Wicket, using the ResourceLink approach (since the download is not a static file, it needs to be generated on the fly, and I was told this was the correct approach):
IResource res = new AbstractResource() {
#Override
protected ResourceResponse newResourceResponse(Attributes attributes) {
ResourceResponse resourceResponse = new ResourceResponse();
resourceResponse.setContentType("application/pdf");
resourceResponse.setFileName("output.pdf");
resourceResponse.setContentDisposition(ContentDisposition.ATTACHMENT);
resourceResponse.setWriteCallback(new WriteCallback() {
#Override
public void writeData(Attributes attributes) throws IOException {
OutputStream outputStream = attributes.getResponse().getOutputStream();
try {
outputStream.write(generateDocument());
} catch (Exception e) {
//Generation failed... Here I'd like to either show a popup message or alter the current page to show an error somewhere in the page
}
}
});
return resourceResponse;
}
};
ResourceLink<Void> resLink = new ResourceLink<Void>("resLink", res);
myForm.add(resLink);
The comment in the code above shows where I'm having trouble. If the generation of the download fails (which can happen, if certain conditions are not met) I'd like to show an error message, either by showing a popup or altering the page to show some error text (but in either case I want to avoid leaving/reloading the entire page)
Is this possible?
Here's the link with the answer:
https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
Don't forger to use a try/catch with an error(e.getMessage()) inside the catch and a target.add(feedbackPanel) after catching the error.
I am not sure this is possible because you need to use non-Ajax request to be able to download as ATTACHMENT. But since it is non-Ajax request you will need to either reload the current page or redirect to another page in case of an error.
I want to test the file upload in my application. The upload itself is handled as described in section Direct file upload on http://www.playframework.org/documentation/2.0/JavaFileUpload.
I am using the latest Play20 version and build it as described here.
My current code looks like this, but obviously the part is missing which adds a test file to the request:
Test.java
FakeRequest request = fakeRequest(POST, "/measurement/123/file");
// how to append test file to this request?
Result result = routeAndCall(request);
assertOK(result);
Controller.java
public static uploadFile() {
RequestBody body = request().body();
if (body != null) {
RawBuffer rawBuffer = body.asRaw();
if (rawBuffer != null) {
File uploadedFile = rawBuffer.asFile();
// ...
}
}
return ok();
}
My solution for Play 2 Java file upload testing has been to create a UploadFakeRequest extending FakeRequest. Inside the class I have then my own withRawBody method with something like that:
RawBuffer raw = new RawBuffer(1000, data.getBytes()); // No clue what is the correct value here...
AnyContentAsRaw content = new AnyContentAsRaw(raw);
fake = new play.api.test.FakeRequest(POST, fake.path(), new play.api.test.FakeHeaders(Scala.asScala(map)), content, "127.0.0.1");
The signature of the FakeRequest call, as per source code, is:
case class FakeRequest[A](method: String, uri: String, headers: FakeHeaders, body: A) extends Request[A]
You should be able to inspect the body of a POST request that uploads a file to your application and copy that body as a parameter in your testing code. The alternative is to build it as per RFC description on multipart POST.
I am developing my first project with Tapestry and I am about to finish, except for the images..
What do I want? I just need to display an image outside my application, example: /home/app/images/image.jpg
What did I try? I have been "googling" and reading Tapestry5 forums, I found this: http://wiki.apache.org/tapestry/Tapestry5HowToStreamAnExistingBinaryFile
I followed the steps, creating classes but I need to display the image embed on another page (so I can't use ImagePage), I tried this:
On page java class
public StreamResponse getImage() {
InputStream input = DetallesMultimedia.class
.getResourceAsStream("/home/santi/Escritorio/evolution-of-mario.jpg"); //On application, i will retrieve this from DB
return new JPEGInline(input,"hellow");
}
On page template
...
<img src="${image}" alt:image/>
...
or
...
${image}
...
Obviusly, this didn't work and I really don't know how can I do it. I read about loading the image on an event (returning the OutputStream on that event, as it's said in the HowTo linked above) but my english is so bad (I am sure you already noticed) and I don't understand well how can I do that.
Could you help me please?
Thanks you all.
I've never seen the examples as on the wiki page. Below some code on how to load an image on the classpath though using a StreamResponse.
#Inject
private ComponentResources resources;
#OnEvent(value = "GET_IMAGE_STREAM_EVENT")
private Object getProfilePic() throws Exception {
InputStream openStream = DetallesMultimedia.class.getResourceAsStream("/home/santi/Escritorio/evolution-of-mario.jpg");
byte[] imageBytes = IOUtils.toByteArray(openStream);
final ByteArrayInputStream output = new ByteArrayInputStream(imageBytes);
final StreamResponse response = new StreamResponse() {
public String getContentType() {
"image/jpegOrPngOrGif";
}
public InputStream getStream() throws IOException {
return output;
}
public void prepareResponse(Response response) {
// add response headers if you need to here
}
};
return response;
}
public String getPicUrl() throws Exception {
return resources.createFormEventLink("GET_IMAGE_STREAM_EVENT");
}
In your template:
<img src="${picUrl}"/>
i am trying to have a REST service return a zip file from the local harddrive .
Following is what i am doing ,
#Path("/interface3/{Ent_id}/{esf_app_id}/{esf_app_ver}")
public class Interface3Mock {
// This method is called if TEXT_PLAIN is request
#GET
#Produces("application/zip")
public Response callInterface3_text(
#PathParam("Ent_id") Integer entitlement_id,
#PathParam("eapp_id") String eapp_id,
#PathParam("eapp_ver") String eapp_ver) {
File f = new File("D:\\Documentation\\Documentation.zip");
String mt = new MimetypesFileTypeMap().getContentType(f);
return Response.ok(f, mt).build();
}
}
Now when i use the browser ie. Internet Explorer and key in the url http://localhost:9788/mockRESTServer/rest/interface3/123456/k123/l345
i see a file download dialog that says "Do you want to save the file l345`.
i want it to ask me for the zip download ie. D:\\Documentation\\Documentation.zip.
But somehow it takes up the last parameter in the request URL.
return Response.ok(f, mt)
.header("Content-Disposition", "attachment; filename=Documentation.zip")
.build();
See How to set response header in JAX-RS so that user sees download popup for Excel?