Download the file from database without saving it on server - java

I want to retrieve the pdf (Stored as BLOB) from Database using jersey api
I am using mybatis as data base framework .
I am able to download the pdf but the problem is i get the input stream as database to which i save it as file and then pass that it in Response but i don't want to save that file in server , i want file directly to be downloaded to user .
Current Process :
DATABASE-------> input stream-----> File -----------> add to response ----->user downloads it
retrieving making file passing file user downloads
What i want :
DATABASE---------->input stream------------> add to response -------> user downloads it
retrieving passing file user downloads
I want remove File making in server as data is confidential
Resource interface
#GET
#Path("v1/download/{id}")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(#PathParam("id") int id) throws IOException, SQLException;
Resource Impl
#Override
public Response downloadFile(int id) throws IOException, SQLException {
// TODO Auto-generated method stub
File file = fileUploadService.downloadFile(id);
ResponseBuilder response = Response.ok(file);
response.header("Content-Disposition", "attachment;filename=aman.pdf");
return response.build();
}
Service method
#Override
public File downloadFile(int id) throws IOException {
// TODO Auto-generated method stub
File fil=new File("src/main/resources/Sample.pdf");
FileUploadModel fm =mapper.downloadFile(id);
InputStream inputStream = fm.getDaFile();
outputStream = new FileOutputStream(fil);
int read = 0;
byte[] bytes = new byte[102400000];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
return fil;
}
This code is working but i want to remove making of file on server side i.e i want to remove File fil=new File("src/main/resources/Sample.pdf"), this operation which is in service method .
Thanks in advance.

Instead of using File, use ByteArrayOutputStream and write to it. Then return the result as a byte[] which you can pass to your Response.ok(content).
Didn't test this, but something like this:
public byte[] downloadFile(int id) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileUploadModel fm =mapper.downloadFile(id);
InputStream inputStream = fm.getDaFile();
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
return out.toByteArray();
}
Also, that's a lot of bytes to allocate to an array. You can experiment with what works for you, but something like 1024 would likely be totally sufficient.
You'll probably also want to add another header to your response for Content-Type.

Related

How to Create android supported video file (e.g. mp4) using InputStream object in Android

In my Android app I'm downloading Video file using Quickblox API, on successful download I'm getting file content in the form of InputStream object now, using that InputStream object I wants to create android supported Video file and stored it on to the SDCard but I don't know how to create Video file using InputStream object. Please see the following code where I'm getting InputStream object.
QBContent.downloadFileTask(fileId, new QBEntityCallbackImpl<InputStream>()
{
#Override
public void onSuccess(InputStream inputStreamObject, Bundle params)
{
// TODO Auto-generated method stub
super.onSuccess(inputStreamObject, params);
});
}
Please help. Thank you..!
If the inputStreamObject is the content of an mp4 file, you could simply save the input stream to a file. That's your mp4 .
public static final String PREFIX = "myMusicfile";
public static final String SUFFIX = ".mp4";
public static File stream2file (InputStream in) throws IOException {
final File tempFile = File.createTempFile(PREFIX, SUFFIX);
tempFile.deleteOnExit();
try (FileOutputStream out = new FileOutputStream(tempFile)) {
IOUtils.copy(in, out);
}
return tempFile;
}
Hope it help :)
Thanks

File download returns corrupted file (I think) in Play framework 2.2.2

I'm struggling with getting file upload/download to work properly in Play framework 2.2.2. I have a Student class with a field called "cv". It's annotated with #Lob, like this:
#Lob
public byte[] cv;
Here are the upload and download methods:
public static Result upload() {
MultipartFormData body = request().body().asMultipartFormData();
FilePart cv = body.getFile("cv");
if (cv != null) {
filenameCV = cv.getFilename();
String contentType = cv.getContentType();
File file = cv.getFile();
Http.Session session = Http.Context.current().session();
String studentNr = session.get("user");
Student student = Student.find.where().eq("studentNumber", studentNr).findUnique();
InputStream is;
try {
is = new FileInputStream(file);
student.cv = IOUtils.toByteArray(is);
} catch (IOException e) {
Logger.debug("Error converting file");
}
student.save();
flash("ok", "Vellykket! Filen " + filenameCV + " ble lastet opp til din profil");
return redirect(routes.Profile.profile());
} else {
flash("error", "Mangler fil");
return redirect(routes.Profile.profile());
}
}
public static Result download() {
Http.Session session = Http.Context.current().session();
Student student = Student.find.where().eq("studentNumber", session.get("user")).findUnique();
File f = new File("/tmp/" +filenameCV);
FileOutputStream fos;
try {
fos = new FileOutputStream(f);
fos.write(student.cv);
fos.flush();
fos.close();
} catch(IOException e) {
}
return ok(f);
}
The file seems to be correctly saved to the database (the cv field is populated with data, but it's obviously cryptic to me so I don't know for sure that the content is what it's supposed to be)
When I go to my website and click the "Download CV" link (which runs the download action), the file gets downloaded but can't be opened - saying the PDF viewer can't recognize the file etc. (Files uploaded have to be PDF)
Any ideas on what might be wrong?
Don't keep your files in DB, filesystem is much better for that! Save uploaded file on the disk with some unique name, then in your database keep only path to the file as a String!
It's cheaper in longer run (as said many times)
It's easier to handle downloads, i.e. in Play all you need to serve PDF is:
public static Result download() {
File file = new File("/full/path/to/your.pdf");
return ok(file);
}
it will set proper headers, like Content-Disposition, Content-Length and Content-Type not only for PDFs

How can receive multiple files in InputStream and process it accordingly?

I want to receive the multiple files uploaded from my client-side. I uploaded multiple files and request my server-side (Java) using JAX-RS(Jersey).
I have the following code,
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void upload(#Context UriInfo uriInfo,
#FormDataParam("file") final InputStream is,
#FormDataParam("file") final FormDataContentDisposition detail) {
FileOutputStream os = new FileOutputStream("Path/to/save/" + appropriatefileName);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
}
How can i write the files separately in the server side as uploaded in the client side.
For eg. I uploaded files such as My_File.txt, My_File.PNG, My_File.doc.
I need to write as same as the above My_File.txt, My_File.PNG, My_File.doc in the server side.
How can I achieve this?
You could try something like this:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void upload(FormDataMultiPart formParams)
{
Map<String, List<FormDataBodyPart>> fieldsByName = formParams.getFields();
// Usually each value in fieldsByName will be a list of length 1.
// Assuming each field in the form is a file, just loop through them.
for (List<FormDataBodyPart> fields : fieldsByName.values())
{
for (FormDataBodyPart field : fields)
{
InputStream is = field.getEntityAs(InputStream.class);
String fileName = field.getName();
// TODO: SAVE FILE HERE
// if you want media type for validation, it's field.getMediaType()
}
}
}
There is a blog for the scenario you are looking for. Hope this helps
http://opensourzesupport.wordpress.com/2012/10/27/multiple-file-upload-along-with-form-data-in-jax-rs/

JSF application: Open file, not download it

Current situation: I'm trying to create a JSF app (portlet) which should contains links to excel files (xls, xlt) stored on public network drive G: mapped for all users in our company. The main goal is to unify access to these files and save work to users in search of the reports somewhere on G drive. I hope it's clear..?
I'm using following servlet to open a file. Problem is, that it's not just opened, but downloaded by browser and after that, opened:
#WebServlet(name="fileHandler", urlPatterns={"/fileHandler/*"})
public class FileServlet extends HttpServlet
{
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
private String filePath;
public void init() throws ServletException {
this.filePath = "c:\\Export";
System.out.println("fileServlet initialized: " + this.filePath);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
{
String requestedFile = request.getPathInfo();
File file = new File(filePath, URLDecoder.decode(requestedFile, "UTF-8"));
String contentType = getServletContext().getMimeType(file.getName());
response.reset();
response.setBufferSize(DEFAULT_BUFFER_SIZE);
response.setContentType(contentType);
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} finally {
close(output);
close(input);
}
}
private static void close(Closeable resource) {
if (resource != null) resource.close();
}
}
How to just start appropriate application (e.g. Excel, Word, etc.) clicking on link (with absolute file path) and open the file in its original location?
UPDATE: I'm trying to use <a> tag:
File // various "/" "\" "\\" combinations
File
But it doesn't work:
type Status report
message /G:/file.xls
description The requested resource is not available.
File URLs are considered as a security risk by most browsers, because they cause files to be opened on a client's machine by a web page, without the end user being aware of it. If you really want to do that, you'll have to configure the browser to allow it.
See the wikipedia article for solutions.

How to use temp file from which i get inputStream

i am trying to upload a file to the web using rest web service. i created a flow which accept a file in the form as:
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetails,
#FormDataParam("location") String uploadedFileLoc ) {
.
.
}
Here at the end of method, i need to return the file which client uploaded and in the next method that file is converted into the byte array.
Basically i am getting the file in a "InputStream" format. Does there is any way that i could get as an file itself ?
#Ravi Kumar
You can use
public Response uploadFileSimple(#FormDataParam("file") File file, #FormDataParam("file") FormDataContentDisposition formData)
It return you a File object directly, But jersey it self create File object in temp for you, So you can say there is two temp file with same size.
First MIMExxxxx.tmp from where you get you input steam
Second re234xxxx from which you get this file object
NOTE : Before calling your resource method jersey take time to create this two file(as per file size).
And if you want to use directly MIMExx.tmp file, Then i don't think there is straightforward way you may use JAVA REFLECTION to get temp file path and use.
Using Java Reflection :
#Path("/upload/{parentfolderid}")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileWithPart(FormDataMultiPart form)
{
try
{
FormDataBodyPart filePart = form.getField("upload");
BodyPartEntity bodyPart = (BodyPartEntity) filePart.getEntity();
MIMEPart mimePart = (MIMEPart) readFieldValue("mimePart", bodyPart);
Object dataHead = readFieldValue("dataHead", mimePart);
Object dataFile = readFieldValue("dataFile", dataHead);
File tempFile = null;
if (dataFile != null)
{
Object weakDataFile = readFieldValue("weak", dataFile);
tempFile = (File) readFieldValue("file", weakDataFile);
}
else
{
tempFile = filePart.getValueAs(File.class);
}
// Here is your *tempFile*, Do what ever you want with it
}
private static Object readFieldValue(String fieldName, Object o) throws Exception
{
Field field = o.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(o);
}
File is a file, Stream is a stream.
If you need a file from a stream you need to create the file and write the stream into the file.
You can use temp folder for this:
How to create a temp file in java without the random number appended to the filename?
and create a temp file there.
UPD
For your needs, File.createTempFile() should be enough.
You can use the Jersey REST API for file upload. For example,
#Path("/upload")
public class FileUploadService{
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
String location = "/" + fileDetail.getFileName();
// save it
writeToFile(uploadedInputStream, location);
String output = "File uploaded to : " + location;
return Response.status(200).entity(output).build();
}
}
And to save the file you have this method:
private void writeToFile(InputStream uploadedInputStream,
String location) {
try {
OutputStream out = new FileOutputStream(new File(
location));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(location));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Hope it helps!
Thank you all for the suggestion. The main thing i need to do is converting the file to byte array. Since i am getting the InputStream, i could pass this as the return to the next flow rather than waiting for the file itself.
In the next flow rather than using a "file to byte array" transformer, just use "Object to byte array" transformer. Finally it works.

Categories