I'll put my code first:
#Post
public Representation post(InputStream zip) throws Throwable {
createFile(zip, "C:/temp");
return new StringRepresentation("File uploaded");
}
public void createFilee(InputStream zipStream, uploadedFileLocation) throws Exception {
try {
writeToFile(zipStream, uploadedFileLocation);
FileUtils.forceDelete(new File(uploadedFileLocation));
} catch (Exception e) {
throw e;
}
}
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();
uploadedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
When I send a file to my server, it cannot get deleted. When using FileUtils.forceDelete(), it says that it cannot delete the file. I can delete the file manually while the server is still running after it tries to delete the file with file utils. Why can't it just delete it itself?! any ideas? Thanks
EDIT: Could the issue be that the InputStream from the POST is alive until the POST returns? So, even when I call to delete the file, the stream is still kept alive by the POST? Is this even possible?
In my limited windows experience it can be one of the two things
I would check
1) THe anti-virus software is trying to scan the file
2) Some kind of indexer (System or custom) is trying to index the file.
you can use a tool like processExplorer to see which process holding up the file descriptor.
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
Related
Few days ago, I struggled with how to access file sent by NettyClient without killing NettyServer. I got solution on StackOverFlow and the detail of question is here. The solution is that the client close channel after sending the file, and the server close the fileoutputstream in channelInactive method. The main code is below.
ClientHandler
public class FileClientHandler extends ChannelInboundHandlerAdapter {
private int readLength = 128;
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
sendFile(ctx.channel());
}
private void sendFile(Channel channel) throws IOException {
File file = new File("C:\\Users\\xxx\\Desktop\\1.png");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
ChannelFuture lastFuture = null;
for (;;) {
byte[] bytes = new byte[readLength];
int readNum = bis.read(bytes, 0, readLength);
if (readNum == -1) { // The end of the stream has been reached
bis.close();
fis.close();
lastFuture = sendToServer(bytes, channel, 0);
if(lastFuture == null) { // When our file is 0 bytes long, this is true
channel.close();
} else {
lastFuture.addListener(ChannelFutureListener.CLOSE);
}
return;
}
lastFuture = sendToServer(bytes, channel, readNum);
}
}
private ChannelFuture sendToServer(byte[] bytes, Channel channel, int length)
throws IOException {
return channel.writeAndFlush(Unpooled.copiedBuffer(bytes, 0, length));
}
}
ServerHandler
public class FileServerHandler extends ChannelInboundHandlerAdapter {
private File file = new File("C:\\Users\\xxx\\Desktop\\2.png");
private FileOutputStream fos;
public FileServerHandler() {
try {
if (!file.exists()) {
file.createNewFile();
} else {
file.delete();
file.createNewFile();
}
fos = new FileOutputStream(file);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void channelInactive(ChannelHandlerContext ctx) {
System.out.println("I want to close fileoutputstream!");
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
ByteBuf buf = (ByteBuf) msg;
try {
buf.readBytes(fos, buf.readableBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
buf.release(); // Should always be done, even if writing to the file fails
}
}
}
If now I need to send 10 thousands pictures but every picture is small like 1KB. I have to close and then establish channel frequently. It is a thing wasting many resources. How can I only close fileoutputstream but the channel is alive?
This is just an idea, and I have not tested it, but rather than sending each file in its own connection, you could start a stream where you send:
The number of files to be sent (once)
The file info and content (for each file)
The file size
The file name size
The file name
The file content (bytes)
The client would look something like this:
public void sendFiles(Channel channel, File...files) {
ByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT;
int fileCount = files.length;
// Send the file count
channel.write(allocator.buffer(4).writeInt(fileCount));
// For each file
Arrays.stream(files).forEach(f -> {
try {
// Get the file content
byte[] content = Files.readAllBytes(f.toPath());
byte[] fileName = f.getAbsolutePath().getBytes(UTF8);
// Write the content size, filename and the content
channel.write(allocator.buffer(4 + content.length + fileName.length)
.writeInt(content.length)
.writeInt(fileName.length)
.writeBytes(fileName)
.writeBytes(content)
);
} catch (IOException e) {
throw new RuntimeException(e); // perhaps do something better here.
}
});
// Flush the channel
channel.flush();
}
On the server side, you would need a slightly more sophisticated channel handler. I was thinking of a replaying decoder. (Example here)
In that example, the decoder will read all the files and then forward to the next handler which would receive a list of Upload instances, but you could send each upload up the pipeline after each received file so you don't allocate as much memory. But the intent is to send all your files in one stream rather than having to connect/disconnect for each file.
I am doing the file operations (file copying from one location to another) .
When the file size is less than 2GB copying is working fine. But, if it is more than that , giving
<BEA-000449> <Closing socket as no data read from it on ***.***.***.***:port_no, during the configured idle timeout of 5 secs>
Code goes as below,
private void copyFile(InputStream uploadedInputStream,
String uploadedFileLocation, boolean append) {
File publicFile;
OutputStream out = null;
try {
publicFile=new File(uploadedFileLocation);
out = new FileOutputStream(publicFile,append);
int read;
byte[] bytes = new byte[1024];
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
} catch (IOException e) {
System.out.println("Exception in transfering file" +e.getMessage());
}finally
{
try{
if(out!=null)out.close();
}catch (IOException e) {
e.printStackTrace();
}
}
Solution I got after browsing is tuning of the server. Is there any other way I can make it work ?
So here is the situation:
I have a .xslm file (a macro enabled excel worksheet) on server. There are no issues in opening this file on server (using ms-excel 2013).
I then edit the file using Apache POI 3.13. Save a copy of this file on server and give the other to the user for download.
(This is done just to check if we have any write issues while editing. The original purpose was just to give it as download)
The copy of this file saved on server is opened without any issues. But the one sent as download throws this error while opening it from excel 2013.
I am using Jquery.fileDownload() on the client side to make the ajax call to the server where I have my Spring Controller serving the file.
Here is my code to write the file:
Workbook workbook = null;
ServletOutputStream out = null;
InputStream inputStream = null;
FileOutputStream fos = null;
try {
OPCPackage inputFilePackage = OPCPackage.open(<original file saved on server>);
workbook = WorkbookFactory.create(inputFilePackage);
//Do Some stuff to edit workbook here
fos = new FileOutputStream("temp.xlsm");
workbook.write(fos);
fos.close();
inputStream = new FileInputStream("temp.xlsm"); // The file that is created just now
servletResponse.setContentType("application/vnd.ms-excel.sheet.macroEnabled.12");
servletResponse.setHeader("content-disposition", "attachment; filename=NewFile.xlsm");
servletResponse.setHeader("Set-Cookie", "fileDownload=true; path=/");
out = servletResponse.getOutputStream();
// workbook.write(out); // Was previously using this method to directly write to ServletOutputStream
int i;
while ((i = inputStream.read()) != -1) {
out.write(i);
}
out.flush();
// new File("temp.xlsm").delete();
}
catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
finally {
if (out != null) {
try {
out.close();
}
catch (Exception ex) {
LOGGER.error(ex.getMessage());
}
}
if (inputStream != null) {
try {
inputStream.close();
}
catch (Exception ex) {
LOGGER.error(ex.getMessage());
}
}
}
return "success";
Also I can clearly see the difference between the size of both the files.
The file which is opening without issues is (436,129 bytes) while the file throwing the error is (436,136 bytes). I am not sure from where these extra bytes are coming.
Any help would be greatly appreciated.
I am creating Restful web service that accepts any file and saves it into filesystem. I am using Dropwizard to implement the service and Postman/RestClient to hit the request with data. I am not creating multipart (form-data) request.
Every thing is working fine except the file saved has first character missing. Here is my code for calling the service method and saving it into file system:
Input Request:
http://localhost:8080/test/request/Sample.txt
Sample.txt
Test Content
Rest Controller
#PUT
#Consumes(value = MediaType.WILDCARD)
#Path("/test/request/{fileName}")
public Response authenticateDevice(#PathParam("fileName") String fileName, #Context HttpServletRequest request) throws IOException {
.......
InputStream inputStream = request.getInputStream();
writeFile(inputStream, fileName);
......
}
private void writeFile(InputStream inputStream, String fileName) {
OutputStream os = null;
try {
File file = new File(this.directory);
file.mkdirs();
if (file.exists()) {
os = new FileOutputStream(this.directory + fileName);
logger.info("File Written Successfully.");
} else {
logger.info("Problem Creating directory. File can not be saved!");
}
byte[] buffer = new byte[inputStream.available()];
int n;
while ((n = inputStream.read(buffer)) != -1) {
os.write(buffer, 0, n);
}
} catch (Exception e) {
logger.error("Error in writing to File::" + e);
} finally {
try {
os.close();
inputStream.close();
} catch (IOException e) {
logger.error("Error in closing input/output stream::" + e);
}
}
}
In output, file is saved but first character from the content is missing.
Output:
Sample.txt:
est Content
In above output file, character T is missing and this happens for all the file formats.
I don't know what point I am missing here.
Please help me out on this.
Thank You.
I have been trying many ways of downloading a file from a URL and putting it in a folder.
public static void saveFile(String fileName,String fileUrl) throws MalformedURLException, IOException {
FileUtils.copyURLToFile(new URL(fileUrl), new File(fileName));
}
boolean success = (new File("File")).mkdirs();
if (!success) {
Status.setText("Failed");
}
try {
saveFile("DownloadedFileName", "ADirectDownloadLinkForAFile");
} catch (MalformedURLException ex) {
Status.setText("MalformedURLException");
Logger.getLogger(DownloadFile.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Status.setText("IOException Error");
Logger.getLogger(DownloadFile.class.getName()).log(Level.SEVERE, null, ex);
}
I found this code on the net, am i using it correctly?
If i did:
saveFile("FolderName", "ADirectDownloadLinkForAFile")
I would get IOException error
What I want my code to do is:
Create folder
Download file
Downloaded file to go to the just created folder
I'm a newbie here sorry. Please help
There are various ways in java to download a file from the internet.
The easiest one is to use a buffer and a stream:
File theDir = new File("new folder");
// if the directory does not exist, create it
if (!theDir.exists())
{
System.out.println("creating directory: " + directoryName);
boolean result = theDir.mkdir();
if(result){
System.out.println("DIR created");
}
}
FileOutputStream out = new FileOutputStream(new File(theDir.getAbsolutePath() +"filename"));
BufferedInputStream in = new BufferedInputStream(new URL("URLtoYourFIle").openStream());
byte data[] = new byte[1024];
int count;
while((count = in.read(data,0,1024)) != -1)
{
out.write(data, 0, count);
}
Just the basic concept. Dont forget the close the streams ;)
The File.mkdirs() statement appears to be creating a folder called Files, but the saveFile() method doesn't appear to be using this, and simply saving the file in the current directory.