I need to save a file and download file in directory outside server context.
I am using Apache Tomacat
I am able to do this in directory present in webapps directory of application
If my directory structure is as follows,
--src
--WebContent
-- uploaddir
-- myfile.txt
Then I am able to download in by simply.
download
But, problem is when file is in some other directory say d:\\uploadedfile\\myfile.txt
then I wont be able to download it, as resource is not in server context as above.
I have file path to uuid mapping,
like,
d:\\uploadedfiles\\myfile.txt <-> some_uuid
then I want file should be downloaded, on click of following,
download
So, How to make file downloadable when it is outside the server context,
I heard about getResourceAsStream() method which would do this , But would any one help me on how to do this, probably with simple code snippet?
Try the below code which you can write in filedownloadservet. Fetch the file name from the request parameter and then read and write the file.
If you need to do some security checks then do that before processing the request.
File file = new File("/home/files", "file name which user wants to download");
response.setContentType(getServletContext().getMimeType(file.getName()));
response.setContentLength(file.length());
BufferedInputStream inputStream = null;
BufferedOutputStream outputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
outputStream = new BufferedOutputStream(response.getOutputStream());
byte[] buf = new byte[2048];
int len;
while ((len = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, len);
}
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
//log it
}
}
// do the same for input stream also
}
here i found the answer,
response.setContentType("application/msword");
response.setHeader("Content-Disposition","attachment;filename=downloadname.doc");
File file=new File("d:\\test.doc");
InputStream is=new FileInputStream(file);
int read=0;
byte[] bytes = new byte[BYTES_DOWNLOAD];
OutputStream os = response.getOutputStream();
while((read = is.read(bytes))!= -1){
os.write(bytes, 0, read);
}
os.flush();
os.close();
Base path will not work that is for HTML and it works if the base path is also exposed by your web server which does not look like case here.
To download an arbitary file you need to open the file using a FileInputStream (and surround it by a buffered input stream), read a byte, then send that byte from your servlet to the client.
Then there are security concerns, so should google that (basically not give access to any file but only file that is to be shared, audit download etc as needed.
Again in your servlet set the mime type etc and then open a input stream and write the bytes to the output stream to client
Related
I am creating an app that allows the user to upload multiple files to my server and I am doing the uploading with the "Fast Android Networking" Library, so I will need to provide File Objects to upload the files and can not use the Uri's I get from the filechooser.
Currently I'm getting an InputStream from a Uri and copy it into a File.
public static void copyInputStreamToFile(InputStream inputStream,
File file) throws IOException {
try (FileOutputStream outputStream = new FileOutputStream(file, false)) {
int read;
byte[] bytes = new byte[8192];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
}
}
This though, will get any device to lag pretty fast and I'd like to avoid this. I searched everywhere but couldn't find a method for converting a Uri to a File object, that works for me. If anyone knows a way to directly upload from uri, that would also work for me.
I am getting byte array from web service. this byte array is the pdf file. Below code execute well and download file on browser. But this file is seems corrupt. Also additional copy of file gets created on server which I am trying to avoid.
byte[] rawFile = myService.getDocument(param1, param2);
try (BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(rawFile));
FileOutputStream fileOutputStream = new FileOutputStream("myfile-1.pdf")) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
response.setContentType("application/pdf");
response.setHeader("Content-Disposition","attachment;filename=myfile-1.pdf");
response.flushBuffer();
} catch (final Exception ex) {
ex.printStackTrace();
}
}
In a nutshell, below are 2 issue.
Downloaded file (on browser) is seems corrupt and not open. Generic pdf error message appears.
File which created on server is opening fine and shows content. But this file should not be physically present on server.
Downloaded file (on browser) is seems corrupt and not open.
Because you never sent the file content to the browser.
this file should not be physically present on server.
Then why did you explicitly write it there using FileOutputStream?
You need to write the file content to the response.
byte[] rawFile = myService.getDocument(param1, param2);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment;filename=myfile-1.pdf");
OutputStream out = response.getOutputStream();
out.write(rawFile);
// no need to close or flush, that happens automatically when you return
I have the following situation, within a servlet a create a file and then have to delete it.
When executing the file, I figured out that the file is still in the server, so I tried to remove it manually, I can't, I get the following message :
this file is opened by another program : javaw.exe
Here is my code :
public class GenerateFile extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("ok");
String fileName = request.getParameter("fileName");
Integer nbrParam = Integer.parseInt(request.getParameter("nbrParam"));
String[] valueParam = new String[nbrParam+1];
for(int i =1;i<=nbrParam;i++)
{ System.out.println(request.getParameter("param"+i));
valueParam[i]=request.getParameter("param"+i);
}
FileInputStream in = new FileInputStream("C:\\Users\\free\\Desktop\\myworkspace\\gestionRH\\WebRoot\\fiches\\"+fileName+".doc");
POIFSFileSystem fs = new POIFSFileSystem(in);
HWPFDocument doc = new HWPFDocument(fs);
Range r = doc.getRange();
for(int i=1;i<=nbrParam;i++)
{ System.out.println("<param"+i+">");
System.out.println(valueParam[i]);
r.replaceText("<param"+i+">", valueParam[i]);
}
File file = new File("C:\\Users\\free\\Desktop\\myworkspace\\gestionRH\\WebRoot\\fiches\\temp");
File temp = File.createTempFile("monfile",".doc",file);
String tempName =temp.getName();
doc.write( new FileOutputStream(temp));
OutputStream out = response.getOutputStream();
response.setContentType("application/rtf");
response.setHeader("Content-Disposition","attachment; filename=Decision");
FileInputStream in1 = new FileInputStream(temp);
byte[] buffer = new byte[4096];
int length;
while ((length = in1.read(buffer)) > 0){
out.write(buffer, 0, length);
}
in1.close();
out.flush();
System.out.println("C:\\Users\\free\\Desktop\\myworkspace\\gestionRH\\WebRoot\\fiches\\temp\\"+tempName);
File f = new File("C:\\Users\\free\\Desktop\\myworkspace\\gestionRH\\WebRoot\\fiches\\temp\\"+tempName);
f.delete();
return null;
}
}
You should close all the file-reading object instances. Besides, if you can delete the file manually, you should close java and then delete it, javaw is the process that launches java outside the console.
The problem is you are creating a new FileOutputStream(tempName) to write on that file, but never closing that outputstream (or another outputstream linked to it).
Do this:
FileOutputStream fos = newFileOutputStream(tempName);
// use it
fos.close(); // CLOSE IT!!
// then you can delete the file
Simplify
Maybe you could do the work another way, without temp files...
by example: doc.write(new FileOutputStream(tempName)) could be replaced by:
doc.write(response.getOutputStream());
This way doc sends its bytes directly to where you need them, not to a temp file eliminating the need for it.
The idea behind input/output streams is composing them. Input/OutputStream are the abstract base classes. And there are a lot of implementations:
based on memory: ByteArrayInput/OutputStream
based on files: FileInputOutputStream
compressing/decompressing to another outputstream: GZipInputOutputStream
and so on
The beauty of it is applying decorator pattern to add functionality. By example:
new GZipOutputStream(new ByteArrayOutputStream());
// creates an outputstreams that compress data received and send it to the other stream
// the BAOS then writes the received bytes to memory
new GZipOutputStream(new FileOutputStream());
// it's the same but sending compressed bytes to a file.
Seems like, you are not closing the file(out), thus it remains with the thread of this action, which is restricting it to get deleted.
Hope it helps.
maybe you should try ProcMon to find out what process exactly holds the file opened
For IO features, I would to suggest to use some kind of jar already provided by community.
For example, common-io.x-x.jar, spring-core.jar
Eg, org.apache.commons.io.FileUtils;
FileUtils.copyDirectory(from, to);
FileUtils.deleteDirectory(childDir);
FileUtils.forceDelete(springConfigDir);
FileUtils.writeByteArrayToFile(file, data);
org.springframework.util.FileSystemUtils;
FileSystemUtils.copyRecursively(from, to);
FileSystemUtils.deleteRecursively(dir);
good luck!
Whenever you open a file handler, you should close it. In a Java application that you want to run for a long period of time, you are strongly recommended to close all unused file handlers soon after you finish working with them.
Examples of common file handlers are FileOutputStream and FileInputstream. Here is a good example of how you open and close the FileOutputStream
FileOutputStream fos = null;
try {
fos = new FileOutputStream(tempName);
// do something
} catch (IOException ex) {
// deal with exceptions
} finally {
// close if fos is not null
if (fos != null) {
fos.close();
}
}
You should never do this:
doc.write( new FileOutputStream(temp));
because you can never close the file handler if it has no refernce to it.
I need to create a File object out of a file path to an image that is contained in a jar file after creating a jar file. If tried using:
URL url = getClass().getResource("/resources/images/image.jpg");
File imageFile = new File(url.toURI());
but it doesn't work. Does anyone know of another way to do it?
To create a file on Android from a resource or raw file I do this:
try{
InputStream inputStream = getResources().openRawResource(R.raw.some_file);
File tempFile = File.createTempFile("pre", "suf");
copyFile(inputStream, new FileOutputStream(tempFile));
// Now some_file is tempFile .. do what you like
} catch (IOException e) {
throw new RuntimeException("Can't create temp file ", e);
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
Don't forget to close your streams etc
This should work.
String imgName = "/resources/images/image.jpg";
InputStream in = getClass().getResourceAsStream(imgName);
ImageIcon img = new ImageIcon(ImageIO.read(in));
Usually, you can't directly get a java.io.File object, since there is no physical file for an entry within a compressed archive. Either you live with a stream (which is best most in the cases, since every good API can work with streams) or you can create a temporary file:
URL imageResource = getClass().getResource("image.gif");
File imageFile = File.createTempFile(
FilenameUtils.getBaseName(imageResource.getFile()),
FilenameUtils.getExtension(imageResource.getFile()));
IOUtils.copy(imageResource.openStream(),
FileUtils.openOutputStream(imageFile));
You cannot create a File object to a reference inside an archive. If you absolutely need a File object, you will need to extract the file to a temporary location first. On the other hand, most good API's will also take an input stream instead, which you can get for a file in an archive.
I used the following method to download an mp3 file at :
http://online1.tingclass.com/lesson/shi0529/43/32.mp3
But I got the following error :
java.io.FileNotFoundException: http:\online1.tingclass.com\lesson\shi0529\43\32.mp3 (The filename, directory name, or volume label syntax is incorrect)
public static void Copy_File(String From_File,String To_File)
{
try
{
FileChannel sourceChannel=new FileInputStream(From_File).getChannel();
FileChannel destinationChannel=new FileOutputStream(To_File).getChannel();
sourceChannel.transferTo(0,sourceChannel.size(),destinationChannel);
// or
// destinationChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
sourceChannel.close();
destinationChannel.close();
}
catch (Exception e) { e.printStackTrace(); }
}
Yet if I do it from a browser by hand, the file is there, I wonder why it didn't work, and what's the right way to do it ?
Frank
Using old-school Java IO, but you can map this to the NIO method you are using. Key thing is use of URLConnection.
URLConnection conn = new URL("http://online1.tingclass.com/lesson/shi0529/43/32.mp3").openConnection();
InputStream is = conn.getInputStream();
OutputStream outstream = new FileOutputStream(new File("/tmp/file.mp3"));
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) > 0) {
outstream.write(buffer, 0, len);
}
outstream.close();
When you create a FileInputStream, you always access your local filesystem. Instead, you should use a URLConnection for accessing files over HTTP.
The indicator for this is that the forward slashes / have turned into backward slashes \.
FileInputStream is used to access local files only. If you want to access the content of an URL you can setup an URLConnection or use something like this:
URL myUrl = new URL("http://online1.tingclass.com/lesson/shi0529/43/32.mp3");
InputStream myUrlStream = myUrl.openStream();
ReadableByteChannel myUrlChannel = Channels.newChannel(myUrlStream);
FileChannel destinationChannel=new FileOutputStream(To_File).getChannel();
destinationChannel.transferFrom(myUrlChannel, 0, sizeOf32MP3);
Or more simply just make a BufferedInputStream from myUrlStream and cycle the read/write operation until EOF is found on myUrlStream.
Cheers,
Andrea