How to read images from POST call parameter - java

I am looking at consuming an image that has been passed along with a post request as a parameter.
I am unable to understand how to consume this image with java restlet.
I want to use this image and send it for printing.
Thanks in advance.

Here is the code to put in a class extending ServerResource called at the POST of the form:
#Post
public Representation upload(Representation entity) throws Exception {
// 1/ Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2/ Create a new file upload handler based on the Restlet
// FileUpload extension that will parse Restlet requests and
// generates FileItems.
RestletFileUpload upload = new RestletFileUpload(factory);
// 3/ Request is parsed by the handler which generates a
// list of FileItems
List<FileItem> items = upload.parseRepresentation(entity);
String filename = "myImage.png";
File file = new File(filename);
for (FileItem fi : items) {
if (fi.getFieldName().equals("datafile")) {
System.out.println("Save image ... " + filename);
fi.write(file);
}
}
// Print your image
...
}

Related

How do I write a Spring Controller method that returns an image?

I would like to write a Spring controller method which returns an image from storage. Below is my current version, but it has two problems:
The #GetMapping annotation requires the 'produces' parameter which is a string array of media types. The program does not work if that parameter is not present; it just displays the image data as text. The problem is that if I want to support an additional media type then I have to recompile the program. Is there a way to set up the 'produces' media type from inside the viewImg method?
The code below will display any image type except svg, which will display only the message "The image cannot be displayed because it contains errors". The web browser (Firefox) identifies it as media type "webp". However, if I remove all media types from the 'produces' string array except the "image/svg+xml" entry, the image is displayed.
Please advise how to write a controller method that is more general (so that it works with any media type) and does not have issues with svg media type.
Here is my test code:
#GetMapping(value = "/pic/{id}",
produces = {
"image/bmp",
"image/gif",
"image/jpeg",
"image/png",
"image/svg+xml",
"image/tiff",
"image/webp"
}
)
public #ResponseBody
byte[] viewImg(#PathVariable Long id) {
byte[] data = new byte[0];
String inputFile = "/path/to/image.svg";
try {
InputStream inputStream = new FileInputStream(inputFile);
long fileSize = new File(inputFile).length();
data = new byte[(int) fileSize];
inputStream.read(data);
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
I recommend FileSystemResource for handling file contents. You can avoid .contentType(..) started line if you don't want to send Content-Type value.
#GetMapping("/pic/{id}")
public ResponseEntity<Resource> viewImg(#PathVariable Long id) throws IOException {
String inputFile = "/path/to/image.svg";
Path path = new File(inputFile).toPath();
FileSystemResource resource = new FileSystemResource(path);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(Files.probeContentType(path)))
.body(resource);
}

How to serve .jasper file with HTTP Server?

I am creating HTTP server with Tomee, i am placed jasper report file (.jasper) in webapp directory. if i access http://localhost:8080/test.jasper in browser, the browser will prompt to download the file.
In my java project i'm creating simple code to access that link and then preview the report. I use async-http-client library for request.
DefaultAsyncHttpClient client = new DefaultAsyncHttpClient();
BoundRequestBuilder brb = client.prepareGet("http://localhost:8765/qa/test.jasper");
Future<InputStream> f = brb.execute(new AsyncCompletionHandler<InputStream>() {
#Override
public InputStream onCompleted(Response resp) {
try {
String[][] data = {{"Jakarta"},{"Surabaya"},{"Solo"},{"Denpasar"}};
String[] columnNames = {"City"};
DefaultTableModel dtm = new DefaultTableModel(data, columnNames);
Map<String,Object> params = new HashMap<>();
JasperPrint jPrint = JasperFillManager.fillReport(
resp.getResponseBodyAsStream(),
params,
new JRTableModelDataSource(dtm)
);
JasperViewer jpView = new JasperViewer(jPrint,false);
jpView.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
jpView.setSize(800, 600);
jpView.setLocationRelativeTo(null);
jpView.setVisible(true);
} catch (JRException ex) {
System.out.println(ex.getMessage());
}
return resp.getResponseBodyAsStream();
}
});
From my code above, i got an error Error loading object from InputStream
normally i can use
InputStream input = MainContext.class.getResourceAsStream(filename);
But i want to replace file input stream with http request (stream too).
How exactly i can serve .jasper file with http server...?
Error loading object from InputStream error came from corrupt InputStream, if i download .jasper file normally via browser and execute the report with JRLoader.loadObjectFromFile(path to file) it doesn't works too, because tomee give corrupt file (the source file not corrupt).
My own solution is read source file as stream, convert it to base64 encode, and serve it via HTTP API protocol.
finput = new FileInputStream(sPath);
byte[] bFile = Base64.getEncoder().encode(IOUtils.toByteArray(finput));
String sFile = new String(bFile);
inside client side, i received it as body string, decode the base64 string, convert it to InputStream and Finally execute the report with InputStream.
byte[] bBody = Base64.getDecoder().decode(sBody);
InputStream mainReport = new ByteArrayInputStream(bBody);
return JasperFillManager.fillReport(mainReport, params);

Retrieve file from POST request with NanoHttpd

I am trying to use the NanoHttpd library to upload files to my Android server by using a POST request from a form. I do receive the POST request on the server side. My question is how to retrieve the file from the POST request so I can save it somewhere in the device memory.
the form :
<form action='?' method='post' enctype='multipart/form-data'>
<input type='file' name='file' />`enter code here`
<input type='submit'name='submit' value='Upload'/>
</form>
the serve method :
#Override
public Response serve (IHTTPSession session) {
Method method = session.getMethod();
String uri = session.getUri();
if (Method.POST.equals(method)) {
//get file from POST and save it in the device memory
}
...
}
Last night i found solution it's very easy to upload file....
First you have manage 'TempFileManager'. It's handle temp file directory so it' create file and delete automatically after your work finish like copy,read,edit,move etc...
server.setTempFileManagerFactory(new ExampleManagerFactory());
So now you not have manage temp file it's work automatically...
Manage post request like this
private Response POST(IHTTPSession) {
try {
Map<String, String> files = new HashMap<String, String>();
session.parseBody(files);
Set<String> keys = files.keySet();
for(String key: keys){
String name = key;
String loaction = files.get(key);
File tempfile = new File(loaction);
Files.copy(tempfile.toPath(), new File("destinamtio_path"+name).toPath(), StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException | ResponseException e) {
System.out.println("i am error file upload post ");
e.printStackTrace();
}
return createResponse(Status.OK, NanoHTTPD.MIME_PLAINTEXT, "ok i am ");
}

How to access the asset in workflow process step

I am trying to write a workflow process step for the DAM update asset such that the uploaded asset will be sent to an external service that will modify the asset and then the modified asset can be sent to the Metadata extraction step. So I've added my process step to the DAM update asset like this:
And my code looks like this so far:
public void execute(WorkItem item, WorkflowSession wfsession,MetaDataMap args) throws WorkflowException {
try
{
log.info("Here2 in execute method"); //ensure that the execute method is invoked
final Map<String, Object> map = new HashMap<String, Object>();
map.put( "user.jcr.session", wfsession.getSession());
ResourceResolver rr = resolverFactory.getResourceResolver(map);
String path = item.getWorkflowData().getPayload().toString();
log.info("Here2 path: " + path);
Resource resource = rr.getResource(path);
log.info("Here2 resource: " + resource);
InputStream is = resource.adaptTo(InputStream.class);
log.info("Here2 assets IS: " + is);
}
catch (Exception e)
{
log.info("Here Error");
e.printStackTrace();
}
}
This is what I see in the logs when I upload an asset:
Here2 in execute method
Here2 path: /content/dam/photo1.JPG/jcr:content/renditions/original
Here2 asset: null
Question
My external service has an API accepting requests over HTTP. How should I send over the asset to the external service?
Once the external service modifies the asset, what should I do so that the Metadata extraction step reads the modified asset instead of the original?
In order to access your external service via HTTP, you have to write a client. CQ provides commons-httpclient bundle and you may use it to access the service. Documentation for the library can be found here. I don't know if the service expects that the file will be send using PUT or POST, but httpclient provides all these methods. All you have to do is to provide appropriate InputStream. Adapt your resource to Rendition and use getStream() method to get the InputStream.
When you'll get the modified asset from the webservice, you need to replace the original one:
// rendition = ...; // original rendition object created as above
// newInputStream = ...; // new asset received from your webservice
Asset asset = rendition.getAsset();
asset.addRendition("original", newInputStream, rendition.getMimeType());

Test AJAX file upload

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.

Categories