Issue while Upload file using Multipart Request in Codename One - java

I tried to upload a image to the server, it throws me the Error 405 : Method not found, but from that same Url i can able to Download any files.. following is the code i tried.
private void uploadFileToServer(ActionEvent event) throws IOException
{
try{
InfiniteProgress ip = new InfiniteProgress();
Dialog dlg = ip.showInifiniteBlocking();
dlg.show();
MultipartRequest request = new MultipartRequest();
FileSystemStorage fs = FileSystemStorage.getInstance();
String fileUri = fs.getAppHomePath() + "654319032015150536IR.png";
request.setUrl("http://192.XX.XX.58:XX/HttpFolder/");
request.setPost(true);
InputStream is = FileSystemStorage.getInstance().openInputStream(fileUri);
request.addData("file", is, FileSystemStorage.getInstance().getLength(fileUri), "image/png");
request.setFilename("file", fileUri);
request.setPriority(ConnectionRequest.PRIORITY_CRITICAL);
NetworkManager.getInstance().addToQueue(request);
dlg.dispose();
if (event instanceof NetworkEvent) {
NetworkEvent ne = (NetworkEvent)event;
Dialog.show("Result:", ne.getMetaData().toString(), "","");
}
}
catch(Exception e){
Dialog.show("ERROR", e.getMessage(), "OK",null);
}
}

You can't upload to an arbitrary URL, you need to have a servlet that handles multipart on the POST http method.
We have a demo that includes the server side code here: http://codenameone.com/blog/build-mobile-ios-apps-in-java-using-codename-one-on-youtube.html
Notice that you also did some other "problematic" things in the code such as using PRIORITY_CRITICAL and using the InputStream API rather than just giving the file URL (which is more efficient).

Related

Image, Pdf download not working in Java Rest Api

Im trying to download the image and pdf with the below code
File createdFile = new File("logs/decryptedDocs"+filename);
Path path = Paths.get(createdFile.getAbsolutePath());
logger.info("Path is..{}",path.toUri());
Resource resource = new UrlResource(path.toUri());
headers.add("Content-Disposition", "attachment;filename="+resource.getFilename());
// Try to determine file's content type
String contentType = null;
try {
contentType = httpServletRequest.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException ex) {
logger.info("Could not determine file type.");
}
// Fallback to the default content type if type could not be determined
if(contentType == null) {
contentType = "application/octet-stream";
}
logger.info("ContentType is..{}",contentType);
return ResponseEntity.ok()
.headers(headers)
.contentLength(createdFile.length())
.contentType(MediaType.parseMediaType(contentType))
.body(resource);
In my local it is working and in postman when I checked image was visible but couldn't download directly in postman also but when I try to hit the API from front end, the image is visible in the preview section but getting some error in the response like json parser exception. front end technology used is AngularJs.
please help me on this.

S3 generate download link

I'm having trouble generating a download link for an html file i'm uploading to aws s3 server. I am able to generate the link and access the file. But what I want to happen is that when I click the link is for the file to be downloaded instead of opening it.
Here is and example of the url:
https://wassap_app.s3.us-east-1.amazonaws.com/report/test.html
Below is the code for the method that does the upload:
public boolean uploadFile(String name) {
try {
this.client.putObject(new PutObjectRequest(bucketName, "report/" + name, this.file)
.withCannedAcl(CannedAccessControlList.PublicRead));
String url = client.getUrl(bucketName, "report/" + name).toExternalForm();
System.out.println("################ Download File URL ################");
System.out.println(url);
System.out.println("###################################################");
return true;
} catch (AmazonServiceException ase) {
return false;
} catch (AmazonClientException ace) {
return false;
}
}
You can use the response-content-disposition query parameter as documented here. Your URL will then look like:
https://wassap_app.s3.us-east-1.amazonaws.com/report/test.html?response-content-disposition=attachment%3B%20filename%3D%22report.html%22
But the documentation also states:
You must sign the request, either using an Authorization header or a
pre-signed URL, when using these parameters. They cannot be used with
an unsigned (anonymous) request.
To sign the request for the user you can use a presigned URL. I don't have a Java environment to test right now, but something like the following should work.
GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, "report/" + name);
ResponseHeaderOverrides overrides = new ResponseHeaderOverrides();
overrides.setContentDisposition("attachment; filename=\"report.html\"");
req.setResponseHeaders(overrides);
URL url = this.client.generatePresignedUrl(req);
System.out.println(url);
Call this method:
String url = client.getResourceUrl(bucketName, "report/" + name);
Hope this helps!

Multipart File Upload via REST API corrupts file and increases file size

Am uploading a file (any format doc, docx, pdf, text, etc) as multipart form/data to a REST API from Postman or application UI. The text file uploads fine. All other non-text formats get corrupted. I cant open those files.
The size of the uploaded file increases drastically. Check the following server log:
File size just before call to request.getRequestDispatcher().forward(): 27583
Controller, first line in method:39439
The size of the uploaded file is 27.3Kb
I am guessing the files gets corrupted because of the other data appended to the file.
Controller method is
#RequestMapping(value="/entity/{entity}/{entityId}/type/{type}/{derive}",method = RequestMethod.POST)
#ResponseBody
public String uploadFile(#RequestParam("file") MultipartFile multipartFile,#PathVariable("entity")String entity,#PathVariable("type")String type,#PathVariable("entityId")Long entityId,#PathVariable("derive") boolean derive) throws Exception
Since text file is saving correctly and other files also get written correctly, don't think the code to write the file is incorrect.
Code to get inputStream
public String storeFile(MultipartFile multipartFile, String entity, Long id, String uploadType, boolean isDerive,String customName)
throws Exception
{
try
{
System.out.println(multipartFile.getSize());
String fileName = "";
String contentType = "";
if (multipartFile != null)
{
fileName = multipartFile.getOriginalFilename();
contentType = multipartFile.getContentType();
if (contentType == null)
{
contentType = "application/msword";
}
}
InputStream is = multipartFile.getInputStream();
String filePath = getFileName(entity, uploadType, id, fileName, isDerive,customName);
Helper.storeFile(is, filePath);
precedingPath = precedingPath.length() > 0 ? precedingPath + "/":"";
return precedingPath + filePath;
}
catch (WebException e)
{
e.printStackTrace();
throw e;
}
catch (Exception e)
{
e.printStackTrace();
throw new WebException(e.getMessage(), IHttpConstants.INTERNAL_SERVER_ERROR, e);
}
}
Helper.storeFile
public static File storeFile(InputStream is, String filePath) throws IOException {
try {
String staticRepoPath = null;
if (MasterData.getInstance().getSettingsMap().containsKey(Settings.REPO_LOCATION.toString())) {
staticRepoPath = MasterData.getInstance().getSettingsMap().get(Settings.REPO_LOCATION.toString());
} else {
throw new WebException("Invalid Settings");
}
byte[] buffer = new byte[is.available()];
is.read(buffer);
File targetFile = new File(staticRepoPath + File.separator + filePath);
#SuppressWarnings("resource")
OutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
return targetFile;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
My Ajax request is as follows
var fd = new FormData();
//Take the first selected file
fd.append("file", document.actualFile);
//Generic AJAX call
CandidateService.ajax_uploadDocumentWithDocType($scope.candidate.id, fd, document.docType, function (error, json)
Content type while uploading:
var config = {headers:{'X-Auth-Token':authToken, 'Content-Type': undefined}, transformRequest: angular.identity};
Would anyone know how I can fix this and upload the file successfully?
Q1) Why does the file size change between the request dispatcher and the controller that handles the file data.
Q2) Could this change of file size be the cause of file corruption? Libre Office cause General Input/Output Error.
I figured the problem with the file upload. I had a spring filter in between that was changing the request to a wrappedRequest. This was adding additional data to the multipart data and causing the file to be corrupted.
Well in my case I had this exact same problem when accesing the API through Amazon API Gateway. Turned out I forgot to allow multipart ContentType on API Gateway.
Kind of weird the requests still made it to my server and text files worked fine.

Receiving customized response and file from REST web services

I'm trying to create some REST web services with Java in order to send data, do calculations on the server, and return the result. In a first stage I send and receive information as an excel file (in the future I prefer to use XML or JSON).
Well, after a lots of hours trying it, and reading lots of posts, it seems I'm very close to achieve it, but I don't know how to obtain the final response of the server.
I have a service like this:
#GET
#Path("/test")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile(#QueryParam("IDfile") String IDfile) {
if(IDfile.trim().length() == 0 || IDfile == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("IDfile cannot be blank").build();
}
String uploadedFileLocation = "C:\\FilesWebservice\\" + IDfile;
Boolean sortida = false;
try {
prova prueba = new prova();
sortida = prueba.prova(uploadedFileLocation); //this creates an xls file as response
} catch (Exception ex) {
System.out.println("error" + ex.toString());
Logger.getLogger(ServiceResource.class.getName()).log(Level.SEVERE, null, ex);
}
if (sortida) {
File file = new File("C:\\FilesWebservice\\out\\prediction.xls"); // the File path you want to serve.
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"" ) //optional
.build();
} else
return Response.status(500).entity("It was unable to calculate (Ask God for the reason)").build();
}
It works OK, if I send a GET through the browser I receive the file in my downloads folder, but I need to consume the service with another application. Thus, I'm developing a client with Netbeans, and then, NB created automatic code according to my web service. In this case I have:
public <T> T getFile(Class<T> responseType, String IDfile) throws ClientErrorException {
WebTarget resource = webTarget;
if (IDfile != null) {
resource = resource.queryParam("IDfile", IDfile);
}
resource = resource.path("test");
Builder builder = resource.request(MediaType.APPLICATION_OCTET_STREAM_TYPE);
Invocation invocation = builder.buildGet();
return resource.request(MediaType.APPLICATION_OCTET_STREAM_TYPE).get(responseType);
}
Maybe I added some lines, I can't remember now. Anyway, the service returns a status code, a customised message and the file as attachment. I want to read at least the status code and obviously save the file, but I don't know how can I do it.
I tried to do:
MyJerseyClientAlgA client = new MyJerseyClientAlgA("192.168.1.30");
Object response = client.getFile(Response.class, "3cphkhfu.xls");
but it was unsuccessful to extract the information I need from 'response'.
Any help or ideas would be appreciated.
Many thanks in advance
EDIT:
Thanks #LutzHorn for your reply. I'm not sure if I understand well your proposal, I'll do some tests and if I find a solution I'll post under my question. Anyway, I generated again the automatic code for consuming the REST service, that is:
public <T> T getFile(Class<T> responseType, String IDfile) throws ClientErrorException {
WebTarget resource = webTarget;
if (IDfile != null) {
resource = resource.queryParam("IDfile", IDfile);
}
resource = resource.path("test");
return resource.get(responseType);
}
but I have an error in the last line, it indicates:
cannot find symbol
symbol: method get(Class)
so I changed this line for
return resource.request(MediaType.APPLICATION_OCTET_STREAM_TYPE).get(responseType);
but I'm not sure if this is right.
Well, after some hours searching and testing, this piece of code works. I don't know if it is the best solution, but it does exactly what I want: extract the status and save the file returned by the web service.
public void getFile(String IDfile) throws ClientErrorException {
WebTarget resource = webTarget;
if (IDfile != null) {
resource = resource.queryParam("IDfile", IDfile);
}
resource = resource.path("test");
Invocation inv = resource.request(MediaType.APPLICATION_OCTET_STREAM_TYPE).buildGet();
Response rp = inv.invoke();
InputStream attachment = null;
try {
if (rp.getStatus() == 200) {
attachment = rp.readEntity(InputStream.class); //This method can be invoked only once unless you buffer the response...
ReadableByteChannel rbc = Channels.newChannel(attachment); //website.openStream()
FileOutputStream fos = new FileOutputStream("C://FilesWebservice/solution.xls");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
} else {
System.out.println(rp.getStatus());
}
} catch ( Exception ex) {
ex.printStackTrace();
} finally {
rp.close();
}
}

GWT: Showing PDF created as POST response

I have a servlet in an GWT app thats creates a PDF file with the data given with the post request and sends the responst back:
public void service(HttpServletRequest request, HttpServletResponse response) {
try {
String text = request.getParameter("text");
if (text == null || text.trim().length() == 0) {
text = "no data";
}
//PDF Creation with iText
Document document = new Document();
ByteArrayOutputStream b = new ByteArrayOutputStream();
PdfWriter.getInstance(document, b);
document.open();
document.add(new Paragraph(text));
document.close();
response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentType("application/pdf");
response.setContentLength(b.size());
OutputStream os = response.getOutputStream();
b.writeTo(os);
os.flush();
os.close();
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
I want to show the created PDF to the User. I got this far on the client:
final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST,
GWT.getModuleBaseURL() + "PdfServlet");
rb.setHeader("Content-type", "application/x-www-form-urlencoded");
StringBuffer postData = new StringBuffer();
postData.append(URL.encode("text")).append("=")
.append(URL.encode(Text));
rb.setRequestData(postData.toString());
rb.setCallback(new RequestCallback() {
#Override
public void onResponseReceived(Request request,
Response response) {
if (200 == response.getStatusCode()) {
//What to do here?
} else {
//TODO:Something
}
}
#Override
public void onError(Request request, Throwable exception) {
/TODO:...
}
});
try {
rb.send();
} catch (RequestException e) {
e.printStackTrace();
}
So my question is:
How do I show this PDF to the user?
All i managaged to do is show the pdf with "no data" in it..
Thank you for you help :)
Instead of using a RequestBuilder, you can simply use Window.Location.setUrl(yourDowloadUrl?key=value) and include your parameters in the query String. Note however that you must set the Content-disposition header: attachment header so the browser will prompt you to save or open the file, and not replace your GWT app.
Better even, create a hidden iframe in your html page, and call setUrl on that widget.
The downside of using this approach is that it doesn't allow your client code to capture feedback if something goes wrong server-side and instead of a pdf the call returns HTML with an error string from your web server. If that's very important to you, you should use a polling mechanism that requests the document, which is then produced and saved on the server, and checks every n seconds whether there is something to download. I have implemented something like this, which also prevents timeout issues with large documents. Let me know if you're interested
you should create pdf file from your servlet and stored at somewhere on server. You need to return file path where you stored on the server. And now from GWT you can prompt window to user to download file. Below is the example for downloading file from GWT:
Window.open(GWT.getHostPageBaseURL() + your return path from server, "", "");
I could displayed the created pdf without the need to save the file on the server and keep unique key. It works on Chrome but according to some posts it might be a problems on some old browsers.
Window.open("data:application/pdf;base64," + result, cRFTitle.replace(" ", "_") + ".pdf", "enabled");
As suggested the Result need to be Base64 encoded
B.

Categories

Resources