Downloading File from a server - java

I'm trying to download a file which I have on a server.
If I run my application on local everything works properly and I can download the file. Also, I can download the file from a browser or Windows File explorer.
However, when I upload my application to my server, I can't get the file.
try {
uri = "\\DEVDOCSERVER\DOCUMENTS\sample.xml";
if(uri.contains(".") ) {
String extension = uri.substring(uri.lastIndexOf("."));
File file = new File(uri);
if(file!=null)
logger.error("file size: " + file.length());
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
String fileName = getFileName(uri);
logger.error("file name: " + fileName);
String contentType = "application/octet-stream";
response.setContentType(contentType);
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
response.setContentLength((int) file.length());
ServletOutputStream out = null;
try {
FileInputStream input = new FileInputStream(file);
byte[] buffer = new byte[1024];
out = response.getOutputStream();
int i = 0;
while ((i = input.read(buffer)) != -1) {
out.write(buffer);
out.flush();
}
if(input!=null)
logger.error("file input: " + input.toString());
FacesContext.getCurrentInstance().responseComplete();
} catch (IOException err) {
err.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException err) {
err.printStackTrace();
}
}
}
} catch (InternacionalizacionFwException e) {
e.printStackTrace();
}
When I check log, I get next error: (No such file or directory) and the file size is 0

Which Server - Linux, Windows etc. In Linux env its path should be set to forward slash e.g /opt/something/yourfile. Also please log the file path to know in run time location for file you are looking which will help you understand the cause of issue.

Finally, I solved my problem changing the file path depending if I'm working on Windows or Linux.
I also moved the file to another folder because it seemed that I hadn't permissions in the folder I was.
And I had to change the way I was reading the file, because I was getting and error "Error: Network Error" when I was downloading file
Now I'm reading with apache commons:
FileUtils.copyFile(file, response.getOutputStream());

Related

Problem reading the text from the file - FileNotFoundException

I wrote a sample text in the notebook. Then I saved the file on the desktop by calling it TEST. When I try to read its contents, unfortunately in the following code I receive the message: "The file can not be opened".
What could I do to read the text from the TEST file?
This is my code:
public static void main(String[] args) {
int i;
FileInputStream fin;
//Checks whether the file name was specified
if(args.length !=1) {
System.out.println("Usage: ShowFile TEST.TXT");
return;
}
//Try open
try {
fin = new FileInputStream(args[0]);
} catch(FileNotFoundException exc) {
System.out.println("The file can not be opened!");
return;
}
//At this stage, the file is open and ready to read, the following code reads the characters to reach the end of the file
try {
do {
i = fin.read();
if(i != -1) System.out.println((char)i);
} while(i != -1);
} catch (IOException exc) {
System.out.println("Error reading the file");
}
//Close file
try {
fin.close();
} catch(IOException exc) {
System.out.println("Error close file!");
}
}
On the command line i wrote:
TEST.TXT
Try this
BufferedReader br = new BufferedReader(new FileReader(new File("TEST")));
Sytem.out.println(br.readLine());
Of course You would get an Error.!
Because by default FileInputStream() would check for the file in the current directory i.e
in the directory where your java source file is located. And as you have saved your TEST.TXT on your Desktop.
So to open your file located in Desktop folder. Just provide the absolute path of your file to the FileInputStream.
For example, if file is stored at C:\Users\user\Desktop\TEST.txt
then
file = new FileInputStream("C:\Users\user\Desktop\TEST.txt");
Thankyou and Happy coding..!
That is because not the full path is given, and the working directory is the taken as starting directory. That path is in System.getProperty("home.dir").
Path path = Paths.get("TEST.txt");
System.out.println("Full path: " + path.toAbsolutePath());
You might use for the desktop:
System.getProperty("home.user") + "/Desktop/" + args[0]

Reading a resource file from within compiled jar, return as file

I've read this Reading a resource file from within jar however I couldn't figure out how to get a file instead of a inputstream, which is what I need. This is the code:
private void duplicateDocument() {
FileOutputStream fos = null;
File file;
try {
try {
doc = new File(getClass().getResource("1.docx").toURI());
//doc = new File(getClass().getResourceAsStream("1.docx"));
} catch (URISyntaxException ex) {
Logger.getLogger(ForensicExpertWitnessReportConfigPanel.class.getName()).log(Level.SEVERE, "Failed ...", ex);
}
file = new File("C:\\Users\\student\\Documents\\myfile.docx");
fos = new FileOutputStream(file);
/* This logic will check whether the file
* exists or not. If the file is not found
* at the specified location it would create
* a new file
*/
if (!file.exists()) {
file.createNewFile();
}
/*String content cannot be directly written into
* a file. It needs to be converted into bytes
*/
byte[] bytesArray = FileUtils.readFileToByteArray(doc);
fos.write(bytesArray);
fos.flush();
System.out.println("File Written Successfully");
}
catch (IOException ioe) {
ioe.printStackTrace();
}
finally {
try {
if (fos != null)
{
fos.close();
}
}
catch (IOException ioe) {
System.out.println("Error in closing the Stream");
}
}
}
FileUtils.readFileToByteArray is the only thing I've been able to get working so far, which is why I need the value a a file rather than an inputstream.
Currently, the code above gives "A java.lang.IllegalArgumentException" which is why I saw a suggestion online to use getResourceAsStream() instead - however haven't been able to return it as a file.
My next option is to try Reading a resource file from within jar - buffered reader instead.
Can someone help?
I recommend Files with its many useful functions:
Path out = Paths.get("C:\\Users\\student\\Documents\\myfile.docx");
InputStream in = getClass().getResourceAsStream("1.docx");
Files.copy(in, out, StandardCopyOption.REPLACE_EXISTING);
A resource in principle is a read-only file, possibly zipped in a jar.
Hence one cannot write back to it, and it can only serve as template for a real file, as is done here.
I got it working, using this:
InputStream in = getClass().getResourceAsStream("1.docx");
byte[] bytesArray = IOUtils.toByteArray(in);

How to copy file from smb share to local drive using jcifs in Java?

Could anybody help me to copy file from shared folder to local drive? My code is:
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import jcifs.smb.SmbFileOutputStream;;
public class smb {
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String urlToBackUpFile = "smb://ip/backup$/test.txt";
System.out.println("smb folder of source file" + urlToBackUpFile);
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(null, "login", "pass");
SmbFile dir = new SmbFile(urlToBackUpFile, auth);
System.out.println(dir.getDate());
SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE/v2.bak");
dir.copyTo(dest);
}
}
File file is not copied. I received a message "Failed to connect to server", but the programm shows dir.getDate() (and file name, and lenght) of source file. So I think the problem with destination folder (C:/SQLRESTORESTAGE/). Also I have proviledges only for reading source file. Could you help me to cirrect the code or advise something? Thank you.
maybe adding auth to the second file:
SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE/v2.bak",**auth**);
using SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE",auth).canWrite
you know if you have write permissions on the parent directory
After many trials and failures the only method that worked for me reliably was to go old school and use FileInputStream and FileOutputStream like so:
`SmbFile[] files = getSMBListOfFiles(sb, logger, domain, userName, password, sourcePath, sourcePattern);
if (files == null)
return false;
output(sb, logger, " Source file count: " + files.length);
String destFilename;
FileOutputStream fileOutputStream;
InputStream fileInputStream;
byte[] buf;
int len;
for (SmbFile smbFile: files) {
destFilename = destinationPath + smbFile.getName();
output(sb, logger, " copying " + smbFile.getName());
try {
fileOutputStream = new FileOutputStream(destFilename);
fileInputStream = smbFile.getInputStream();
buf = new byte[16 * 1024 * 1024];
while ((len = fileInputStream.read(buf)) > 0) {
fileOutputStream.write(buf, 0, len);
}
fileInputStream.close();
fileOutputStream.close();
} catch (SmbException e) {
OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, SMP issue: " + e.getMessage(), e);
e.printStackTrace();
return false;
} catch (FileNotFoundException e) {
OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, file not found: " + e.getMessage(), e);
e.printStackTrace();
return false;
} catch (IOException e) {
OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, IO problem: " + e.getMessage(), e);
e.printStackTrace();
return false;
}
}`
I got it to work. I had to 'create' the destination file before doing the copy. try adding the middle line below into your original code-snippet and see if that works.
SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE/v2.bak");
dest.createNewFile();
dir.copyTo(dest);
This is for clarification.
"Logon failure: unknown user name or bad password." can show for example when you use 1.3.18 but not in 1.2.25.
it is probably because different compatibility settings:
jcifs.smb.lmCompatibility = 0 or 1: Send LM and NTLM 2)
jcifs.smb.lmCompatibility = 2: Send NTLM in both fields 3)
jcifs.smb.lmCompatibility = 3, 4, or 5: Send just LMv2
First way is to use it before NtlmPasswordAuthentication
jcifs.Config.setProperty( "jcifs.smb.lmCompatibility", "3");
It can resolve this issue.
you must use the file: protocol
SmbFile dest = new SmbFile ("file:" + "C:/SQLRESTORESTAGE/v2.bak");

how to flush the ZipOutputStream periodically in java

I am trying to archive list of files in zip format and then downloading it for the user on the fly...
I am facing out of memory issue when downloading a zip of 1gb size
Please help me how i can resolve this without increasing jvm heap size. i would like to flush the stream periodically..
I AM TRYING TO FLUSH PERIODICALLY BUT THIS IS NOT WORKING FOR ME.
Please find my code attached below:
try{
ServletOutputStream out = response.getOutputStream();
ZipOutputStream zip = new ZipOutputStream(out);
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition",
"attachment; filename=\"ResultFiles.zip\"");
//adding multiple files to zip
ZipUtility.addFileToZip("c:\\a", "print1.txt", zip);
ZipUtility.addFileToZip("c:\\a", "print2.txt", zip);
ZipUtility.addFileToZip("c:\\a", "print3.txt", zip);
ZipUtility.addFileToZip("c:\\a", "print4.txt", zip);
zip.flush();
zip.close();
out.close();
} catch (ZipException ex) {
System.out.println("zip exception");
} catch (Exception ex) {
System.out.println("exception");
ex.printStackTrace();
}
public class ZipUtility {
static public void addFileToZip(String path, String srcFile,
ZipOutputStream zip) throws Exception {
File file = new File(path + "\\" + srcFile);
boolean exists = file.exists();
if (exists) {
long fileSize = file.length();
int buffersize = (int) fileSize;
byte[] buf = new byte[buffersize];
int len;
FileInputStream fin = new FileInputStream(path + "\\" + srcFile);
zip.putNextEntry(new ZipEntry(srcFile));
int bytesread = 0, bytesBuffered = 0;
while ((bytesread = fin.read(buf)) > -1) {
zip.write(buf, 0, bytesread);
bytesBuffered += bytesread;
if (bytesBuffered > 1024 * 1024) { //flush after 1mb
bytesBuffered = 0;
zip.flush();
}
}
zip.closeEntry();
zip.flush();
fin.close();
}
}
}
}
You want to use chunked encoding to send a file that large otherwise the servlet container will try and figure out the size of the data you are trying to send before sending it so it can set the Content-Length header. Since you are compressing files you don't know the size of the data you're sending. Chunked-Encoding allows you to send pieces of the response in smaller chunks. Don't set the content length of the stream. You might try using curl or something to see the HTTP headers in the response your getting from the server. If it isn't chunked then you'll want to figure that out. You'll want to research how to force the servlet container to send chunked encoding. You might have to add this to the response header to make the servlet container send it chunked.
response.setHeader("Transfer-Encoding", "chunked");
The other option would be to compress the file into a temporary file with File.createTemp(), and then send the contents of that. If you compress to a temp file first then you can know how big the file is and set the content length for the servlet.
I guess you are digging in a wrong direction. Try to replace the servlet output stream by a file stream and see if the issue is still here. I suspect your web container tries to collect whole servlet output to calculate content-length before sending http headers.
Another thing...you are performing your close inside your try catch block. This leaves the chance for the stream to stay open on your files if you have an exception, as well as NOT giving the stream the chance to flush to the disk.
Always make sure your close is in a finally block (at least until you can get Java 7 with its try-with-resources block)
//build the byte buffer for transferring the data from the file
//to the zip.
final int BUFFER = 2048;
byte [] data = new byte[BUFFER];
File zipFile= new File("C\:\\myZip.zip");
BufferedInputStream in = null;
ZipOutputStream zipOut = null;
try {
//create the out stream to send the file to and zip it.
//we want it buffered as that is more efficient.
FileOutputStream destination = new FileOutputStream(zipFile);
zipOut = new ZipOutputStream(new BufferedOutputStream(destination));
zipOut.setMethod(ZipOutputStream.DEFLATED);
//create the input stream (buffered) to read in the file so we
//can write it to the zip.
in = new BufferedInputStream(new FileInputStream(fileToZip), BUFFER);
//now "add" the file to the zip (in object speak only).
ZipEntry zipEntry = new ZipEntry(fileName);
zipOut.putNextEntry(zipEntry);
//now actually read from the file and write the file to the zip.
int count;
while((count = in.read(data, 0, BUFFER)) != -1) {
zipOut.write(data, 0, count);
}
}
catch (FileNotFoundException e) {
throw e;
}
catch (IOException e) {
throw e;
}
finally {
//whether we succeed or not, close the streams.
if(in != null) {
try {
in.close();
}
catch (IOException e) {
//note and do nothing.
e.printStackTrace();
}
}
if(zipOut != null) {
try {
zipOut.close();
}
catch (IOException e) {
//note and do nothing.
e.printStackTrace();
}
}
}
Now if you need to loop, you can just loop around the part that you need to add more files to. Perhaps pass in an array of files and loop over it. This code worked for me zipping a file up.
Don't size your buf based on the file size, use a fixed size buffer.

FileNotFoundException (The system cannot find the path specified)

I get this exception:
java.io.FileNotFoundException: C:\...\filename.xml (The system cannot find the path specified)
using this code:
FileWriter fileWriter = new FileWriter(new File(path + date + time "filename.xml"));
BufferedWriter writer = new BufferedWriter(fileWriter);
writer.write("data");
Path exists but directories for 'date' and 'time' need to be created. Application has full permissions on the directory.
Any ideas?
The problem is because I'm creating a subdirectory in which to write the files. So I currently have C:\example\ and want to write my files in C:\example\<date>\<time>\<files>
You need to call File#mkdirs() before writing.
File file = new File("C:/example/newdir/newdir/filename.ext");
file.mkdirs();
// ...
Do assume that the computer is right and you are wrong.
And, in that scenario, the directory to which you want to write does not exit (or does not have permissions to do so).
check the current working dir System.getProperty("user.dir")
debug from there
Code works for me. (Need to add a writer.close() for text to show up in the file.)
What worked for me: The folder where my project was present had a space in the name. I replacedthe space with a hyphen(-). Now, the relative path of the file does not have a space (%20). This change worked for me. Hope it helps someone.
You also need to convert newly created file and folder paths to string.
File folder = new File("src\\main\\json\\", idNumber);
folder.mkdir();
if (!folder.exists()) {
try {
folder.createNewFile();
} catch (IOException ex) {
Logger.getLogger(JsonGeneration.class.getName()).log(Level.SEVERE, null, ex);
}
}
...
...
FileOutputStream output = null;
File file;
String content = data.toString();
try {
String folder_location = folder.toString() + "\\";
String filename = "CurrentInfo";
file = new File(folder_location + filename.toString() + ".json");
output = new FileOutputStream(file);
if (!file.exists()) {
file.createNewFile();
}
byte[] content_in_bytes = content.getBytes();
output.write(content_in_bytes);
output.flush();
output.close();
} catch (IOException ex) {
Logger.getLogger(JsonGeneration.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (output != null) {
output.close();
}
} catch (IOException e) {
Logger.getLogger(JsonGeneration.class.getName()).log(Level.SEVERE, null, e);
}
}
}

Categories