Custom upload component - java

I'm developing my first application in vaadin. Now I'm trying to customize upload component. In summary I have to do the upload of an image.
Now my component is implemented in a standard way:
public OutputStream receiveUpload(String filename,String mimeType) {
// Create upload stream
FileOutputStream fos = null; // Stream to write to
try {
// Open the file for writing.
file = new File("/tmp/uploads/" + filename);
fos = new FileOutputStream(file);
} catch (final java.io.FileNotFoundException e) {
new Notification("Could not open file<br/>",e.getMessage(),Notification.Type.ERROR_MESSAGE).show(Page.getCurrent());
return null;
}
return fos; // Return the output stream to write to
}
I want to ask you, if i can do the upload of the document without use a temp file on server.
How can I do?

Of course,
you just need to provide a OutputStream for the upload component.
This could be a a ByteArrayOutputStream for example, so you have everything as a large bytearray.
Just be aware, when the user uploads a 10 GByte size file, you will also need that much memory on the server for that request
André

Related

How to save a file in the Downloads directory?

My Code is:
String MyFile = "Riseone.dat";
String MyContent = "This is My file im writing\r\n";
File file;
FileOutputStream outputStream;
try {
file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS),MyFile);
outputStream = new FileOutputStream(file);
outputStream.write(MyContent.getBytes());
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
When I try this code MyFile creates in data/data/appfolder/files/Riseone.dat
but I want to create a file in DIRECTORY_DOWNLOADS.
also I want the file to write in append for next write action.
new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), MyFile); corresponds to the file inside the Downloads directory of external shared storage. You might have seen older file in internal storage. Check it carefully.
If you want to append the data for next write, use append mode to create FileOutputStream using another constructor public FileOutputStream(File file, boolean append)
outputStream = new FileOutputStream(file, true);

Resume a Java FTP file download

I'm developing, in Java, an application that has to download from a server to client some very large files. So far I'm using the apache commons-net:
FileOutputStream out = new FileOutputStream(file);
client.retrieveFile(filename, out);
The connection commonly fails before the client finishes downloading the file. I need a way to resume the download of the file from the point where the connection failed, without downloading the whole file again, is it possible?
Things to know:
FileOutputStream has an append parameter, from doc;
#param append if true, then bytes will be written
to the end of the file rather than the beginning
FileClient has setRestartOffset which takes offset as parameter, from doc;
#param offset The offset into the remote file at which to start the
next file transfer. This must be a value greater than or
equal to zero.
We need to combine these two;
boolean downloadFile(String remoteFilePath, String localFilePath) {
try {
File localFile = new File(localFilePath);
if (localFile.exists()) {
// If file exist set append=true, set ofset localFile size and resume
OutputStream fos = new FileOutputStream(localFile, true);
ftp.setRestartOffset(localFile.length());
ftp.retrieveFile(remoteFilePath, fos);
} else {
// Create file with directories if necessary(safer) and start download
localFile.getParentFile().mkdirs();
localFile.createNewFile();
val fos = new FileOutputStream(localFile);
ftp.retrieveFile(remoteFilePath, fos);
}
} catch (Exception ex) {
System.out.println("Could not download file " + ex.getMessage());
return false;
}
}
Commons-net FTPClient supports restarting transfers from a specific offset. You'll have to keep track of what you've successfully retrieved, send the correct offset, and manage appending to the existing file. Assuming, of course, that the FTP server you're connecting to supports the REST (restart) command.

Control Uploaded file types (only specific extension can be uploaded)

i have a stupid question here i'm implementing upload button with vaadin and i want the users to upload only compressed files (.zip,.rar..), imake a search but i didn't find something useful :
so i tried to do this , i know it's not good solution because the user already uploaded the selected file :
#Override
public OutputStream receiveUpload(String filename, String mimeType) {
// Create upload stream
FileOutputStream fos = null; // Stream to write to
String fileName ;
String userHome = System.getProperty( "user.home" );
try {
// Open the file for writing.
file = new File(userHome+"/kopiMap/runtime/uploads/report/" + filename);
fileName= file.getName();
//Here i will get file extension
fos = new FileOutputStream(file);
} catch (final java.io.FileNotFoundException e) {
Notification.show(
"Could not open file<br/>", e.getMessage(),
Notification.TYPE_ERROR_MESSAGE);
return null;
}
return fos; // Return the output stream to write to
}
So how to do it before uploading
you can check the mimeType and if it is application/zip
#Override
public OutputStream receiveUpload(String filename, String mimeType) {
// Create upload stream
if(mimeType.equals("application/zip"))
//Here you can restrict
You can add this and it will work (all done by HTML 5 and most browser support now accept attribute) - this is example for .csv files:
upload.setButtonCaption("Import");
JavaScript.getCurrent().execute("document.getElementsByClassName('gwt-FileUpload')[0].setAttribute('accept', '.csv')");

could not delete file neither via java nor manually

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.

Writing Zip Files to GAE Blobstore

I'm using the Java API for reading and writing to the Google App Engine Blobstore.
I need to zip files directly into the Blobstore, meaning I have String objects which I want to be stored in the Blobstore when zipped.
My problem is that standard zipping methods are using OutputStream to write, while it seems that GAE doesn't provide one for writing to the Blobstore.
Is there a way to combine those APIs, or are there different APIs I can use (I haven't found such)?
If I am not wrong, you can try to use the Blobstore low level API. It offers a Java Channel (FileWriteChannel), so you could probably convert it to an OutputStream:
Channels.newOutputStream(channel)
And use that output stream with the java.util.zip.* classes you are currently using (here you have a related example that uses Java NIO to zip something to a Channel/OutputStream)
I have not tried it.
Here is one example to write content file and zip it and store it into blobstore:
AppEngineFile file = fileService.createNewBlobFile("application/zip","fileName.zip");
try {
FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock);
//convert as outputstream
OutputStream blobOutputStream = Channels.newOutputStream(writeChannel);
ZipOutputStream zip = new ZipOutputStream(blobOutputStream);
zip.putNextEntry(new ZipEntry("fileNameTozip.txt"));
//read the content from your file or any context you want to get
final byte data[] = IOUtils.toByteArray(file1InputStream);
//write byte data[] to zip
zip.write(bytes);
zip.closeEntry();
zip.close();
// Now finalize
writeChannel.closeFinally();
} catch (IOException e) {
throw new RuntimeException(" Writing file into blobStore", e);
}
The other answer is using BlobStore api, but currently the recommended way is to use App Engine GCS client.
Here is what I use to zip multiple files in GCS :
public static void zipFiles(final GcsFilename targetZipFile,
Collection<GcsFilename> filesToZip) throws IOException {
final GcsFileOptions options = new GcsFileOptions.Builder()
.mimeType(MediaType.ZIP.toString()).build();
try (GcsOutputChannel outputChannel = gcsService.createOrReplace(targetZipFile, options);
OutputStream out = Channels.newOutputStream(outputChannel);
ZipOutputStream zip = new ZipOutputStream(out)) {
for (GcsFilename file : filesToZip) {
try (GcsInputChannel readChannel = gcsService.openPrefetchingReadChannel(file, 0, MB);
InputStream is = Channels.newInputStream(readChannel)) {
final GcsFileMetadata meta = gcsService.getMetadata(file);
if (meta == null) {
log.warn("{} NOT FOUND. Skipping.", file.toString());
continue;
}
final ZipEntry entry = new ZipEntry(file.getObjectName());
zip.putNextEntry(entry);
ByteStreams.copy(is, zip);
zip.closeEntry();
}
zip.flush();
}
}

Categories