How to get size of file in rest api jersey - java

I have made a rest api in this it is working fine but i want to read size of file and i have used below code to read size of file
#POST
#Path("/test")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload( FormDataMultiPart form ){
System.out.println(" size of file="+ filePart.getContentDisposition().getSize());
}
but i got the size of file -1 .
Can any one suggest me how can i read actual size of file .
But using
System.out.println(" data name ="+ filePart.getContentDisposition().getFileName());
i got correct name of file .

First of all, I think the best way to restrict data size is setting on the server configuration. Please see the related ref.
Secondly, since it comes with the Stream, it goes til to meet EOF or similar one. That means you cannot find the size at the first place.
Third, however, one of the alternative way for judging size in jersey is using the contents size of the HTTP header. The server gets 'Content-Length' header at the first place to know the size of the body. #Context HttpServletRequest request has request.getContentLength() method. But since it has multiparts, you need to be careful that the body size has sum of the data with protocol overheads (seperator/contents infos)
Good Luck

Hope this is what you wanted. I have verified it in my system. This prints the size of the file in bytes.
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(#FormDataParam("file") InputStream uploadedInputStream, #FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "/home/Desktop/" + fileDetail.getFileName();
// save it
writeToFile(uploadedInputStream, uploadedFileLocation);
File file = new File(uploadedFileLocation);
System.out.println(file.length() + " in bytes");
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation) {
try {
OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
make sure you have the following dependency in your pom.xml
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.13</version>
</dependency>
also add this to your application class which extends resource config. This registers your class with jersey as having multipart content.
super(YourClass.class, MultiPartFeature.class);

Try using HttpServletRequest . Kindly see the docs for more details.
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response putFile(#Context HttpServletRequest request){
Part part = request.getPart("filename");
long fileSize = part.getSize();
}

Related

Jersey HTTP POST method corrupting non-text files

I have a HTTP POST method that works fine if I upload text files. But if I try to upload a word document, pdf, zip, gzip, etc... the files that are uploaded get corrupted in the process. I'm using Postman to send the request. I do a "POST" method, enter the url, add headers (tried all sorts of headers and it really does not change anything so now I don't have any entered), and then on the body I select "formdata" and select the file. I really just need to fix this to be able to support files that end in .csv.gz and .csv. Currently, csv is fine but the .csv.gz is the type that is corrupting. I tried other non-text files as well just to see what happens and they corrupt too. I cannot figure out if there is some encoding, filter, etc... that is causing this to happen that I can remove or some setting I need to apply. Or if there is some other way to handle this with jersey so the non-text files stay the same as the original file.
My application is running Spring v1.5.3 and Jersey 2.25.
#Override
public Response uploadTopicFile(String topic, FormDataMultiPart formDataMultipart) throws Exception {
List<BodyPart> bodyParts = formDataMultipart.getBodyParts();
// Getting the body of the request (should be a file)
for (BodyPart bodyPart : bodyParts) {
String fileName = bodyPart.getContentDisposition().getFileName();
InputStream fileInputStream = bodyPart.getEntityAs(InputStream.class);
String uploadedFileLocation = env.getProperty("temp.upload.path") + File.separator + fileName;
this.saveFile(fileInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
log.debug(output);
}
return Response.status(201).build();
}
private void saveFile(InputStream uploadedInputStream, String serverLocation) {
try {
// Create the output directory
Files.createDirectories(Paths.get(serverLocation).getParent());
// Get the output stream
OutputStream outputStream = new FileOutputStream(new File(serverLocation));
int read = 0;
byte[] bytes = new byte[1024];
// Loop through the stream
while ((read = uploadedInputStream.read(bytes)) != -1) {
// Output to file
outputStream.write(bytes, 0, read);
}
// Flush and close
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
There was a filter causing the corruption. Filter was updated and issue resolved.

Zip file getting downloaded without .zip extension in Chrome through Java

I am trying to download a zip file from a fixed location present in server.
In my Rest method , I am just passing the file name from client (browser) .
(Please see below code ).
In my Rest method I am sending the zip file to the client.
The file gets downloaded on the browser without any issue.
My Issue is that the zip file gets downloaded on browser without .zip extension.
#RequestMapping(value = "/zip/{filePath}", method = RequestMethod.GET)
public #ResponseBody void downloadZip(#PathVariable("filePath") String filePath, HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletContext context = request.getServletContext();
File downloadFile = new File(filePath);
FileInputStream inputStream = new FileInputStream(downloadFile);
// get output stream of the response
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[(int) downloadFile.length()];
int bytesRead = -1;
// write bytes read from the input stream into the output stream
while ((bytesRead = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
// get MIME type of the file
String mimeType = context.getMimeType(fullPath);
if (mimeType == null) {
// set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
System.out.println("MIME type: " + mimeType);
// set content attributes for the response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
response.setHeader("Content-Disposition",
String.format("attachment; filename=\"%s\"", downloadFile.getName()));
logger.error("Filename = " + downloadFile.getName());
inputStream.close();
outStream.close();
}
PS: The file gets downloaded on some machine with ZIP and in some machine without ZIP. I have tested only on chrome (as per client requirement).
I think, there is an issue with the Chrome settings which I need to look upon (just a guess).
Can someone help upon this?
Thanks in advance....
Change the order between setting the response headers and shoving the file down the output stream - after all, the headers need to leave first.
[Edited]
"Why setting HttpServletResponse in starting effects the code."
Well, simple: the client is supposed to receive instructions of what to do with the payload by interpreting the HTTP response headers. If those are not set in the beginning, sending those headers at the end of the transmission comes too late. And this assumes the HttpServletResponse will actually send those headers when invoked with setHeader, which is a big assumption - I suspect those headers will not actually be sent after calling response.getOutputStream - it is unlikely the response will buffer the entire payload to wait for the caller to specify those headers.

Sending multiple images in base64 string through REST web service

What is the best way to right REST web service to send multiple images using JAVA jax-rs?
Although using base64 strings is an option, there are much better ways to go about sending files in a JAX-RS web service. I personally recommend creating a method that listens for the user to POST an HTTP form. This form could really contain all of the information that you would need to send, as well as identifiers.
This is similar to a method definition that I would use for a web service of this type. It is compatible with Jersey, and it allows the user to send files via a basic HTML form or any POST request. I strongly recommend taking a look at this article on building Java web services. It doesn't cover the "file uploading" aspect, but it is extremely useful and it helped me learn much more about the functionality of Java web services in general.
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces("text/html")
public Response uploadFile(
#FormDataParam("username") String username,
#FormDataParam("password") String password,
#FormDataParam("title") String title,
#FormDataParam("file") InputStream fileInputString,
#FormDataParam("file") FormDataContentDisposition fileInputDetails) {
String status = null;
String fileLocation = "/home/user/uploadtest/test.png;
NumberFormat myFormat = NumberFormat.getInstance();
myFormat.setGroupingUsed(true);
// Save the file
try {
OutputStream out = new FileOutputStream(new File(fileLocation));
byte[] buffer = new byte[1024];
int bytes = 0;
long file_size = 0;
while ((bytes = fileInputString.read(buffer)) != -1) {
out.write(buffer, 0, bytes);
file_size += bytes;
}
out.flush();
out.close();
status = "File has been uploaded to:" + fileLocation;
} catch (IOException ex) {
System.err.println("Unable to save file: " + fileLocation);
ex.printStackTrace();
}
return Response.status(200).entity(status).build();
}

Why won't dropwizard upload an xls file?

I've made a pretty conventional file upload method using dropwizard.
So I have a method in the resource that starts off like this
#POST
#Path("/uploadFile")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#UnitOfWork
public Response uploadFile(
#FormDataParam("file") final InputStream fileInputStream,
#FormDataParam("file") final FormDataContentDisposition contentDispositionHeader,
#Context HttpServletRequest request) throws IOException {...
Nothing special inside, it just saves to a path, using java.nio libraries, like so
java.nio.file.Path outputPath = FileSystems.getDefault()
.getPath(System.getProperty("user.home"), fileName);
if (!Files.exists(outputPath.getParent()))
Files.createDirectories(outputPath.getParent());
Files.copy(fileInputStream, outputPath);
It just will not upload an excel file. I read elsewhere that excel files and their underlying type are viewed with suspicion. What do I need to do please?
Basically, the method worked for other files, but would not upload a xls file. I don't know the exact reason, but my suspicions are posted in the question. The way I got it working was to replace the simple copy line
Files.copy(fileInputStream, outputPath);
with
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(new File(outputPath.toString()));
int read = 0;
byte[] bytes = new byte[1024];
while ((read = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
outputStream.flush();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
finally{
outputStream.close();
}
Which gets around (what I suspect is a security feature) by reading the input stream into a byte array, and then writing it into a new FileOutputStream.
If anybody has a "proper way," that is better than this, it would be cool to see it. The stack trace didn't tell me much about what was going on.

Sending Large Image in chunks

I am sending images from my android client to java jersey restful service and I succeded in doing that.But my issue is when I try to send large images say > 1MB its consumes more time so I like to send image in CHUNKS can anyone help me in doing this.How to send(POST) image stream in CHUNKS to server
references used :
server code & client call
server function name
/*** SERVER SIDE CODE****/
#POST
#Path("/upload/{attachmentName}")
#Consumes(MediaType.APPLICATION_OCTET_STREAM)
public void uploadAttachment(
#PathParam("attachmentName") String attachmentName,
#FormParam("input") InputStream attachmentInputStream) {
InputStream content = request.getInputStream();
// do something better than this
OutputStream out = new FileOutputStream("content.txt");
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
// whatever processing you want here
out.write(buffer, 0, len);
}
out.close();
return Response.status(201).build();
}
/**********************************************/
/**
CLIENT SIDE CODE
**/
// .....
client.setChunkedEncodingSize(1024);
WebResource rootResource = client.resource("your-server-base-url");
File file = new File("your-file-path");
InputStream fileInStream = new FileInputStream(file);
String contentDisposition = "attachment; filename=\"" + file.getName() + "\"";
ClientResponse response = rootResource.path("attachment").path("upload").path("your-file-name")
.type(MediaType.APPLICATION_OCTET_STREAM).header("Content-Disposition", contentDisposition)
.post(ClientResponse.class, fileInStream);
You should split the file in the client and restore part of the file in the server.
and after that you should merge the files together. Take a look at split /merge file on coderanch
Enjoy ! :)
Another path is available, if you don't want to code too much consider using :
file upload apache that is great ! :)

Categories

Resources