Best way to close the stream during bulk upload - java

I'm uploading bulk files (say 50000) to Box through Box Java API's. To do that we call the uploadFile method 50000 times. The method also creates and close the file input stream.
Is there a way to keep the stream open until the bulk load is done? Even if I close the stream in finally block, it will close it every time I call the method.
private static String uploadFile(String pathFileName, BoxAPIConnection api, BoxFolder folder) {
boolean fileExists = false;
String fileId = null;
FileInputStream stream = null;
log.debug("Invoked uploadFileAsBoxAppUser-uploadFile :" + pathFileName + ":" + api + ":" + folder);
try {
String fileName = pathFileName.substring(pathFileName.lastIndexOf("\\") + 1, pathFileName.length());
log.debug("fileName :" + fileName);
for (BoxItem.Info itemInfo : folder) {
if (itemInfo instanceof BoxFile.Info) {
BoxFile.Info fileInfo = (BoxFile.Info) itemInfo;
if (fileName.equals(fileInfo.getName())) {
fileExists = true;
fileId = fileInfo.getID();
log.debug("fileExists in Destination box Folder fileID " + fileId);
}
}
}
if (!fileExists) {
log.debug("uploading new file: " + fileName);
stream = new FileInputStream(pathFileName);
BoxFile.Info boxInfo = folder.uploadFile(stream, pathFileName);
fileId = boxInfo.getID();
} else {
log.debug("uploading new version of file: " + fileName);
BoxFile file = new BoxFile(api, fileId);
stream = new FileInputStream(pathFileName);
file.uploadVersion(stream);
}
} catch (IOException e) {
log.debug("Exception in uploadFileAsBoxAppUser :" + e);
}
finally {
if (stream != null)
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return fileId;
}

Related

SparkJava: Upload file did't work in Spark java framework

I have got some method from the stackoverflow about uploading file in spark java, but I try and did't work.
post("/upload",
(request, response) -> {
if (request.raw().getAttribute("org.eclipse.jetty.multipartConfig") == null) {
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(System.getProperty("java.io.tmpdir"));
request.raw().setAttribute("org.eclipse.jetty.multipartConfig", multipartConfigElement);
}
Part file = request.raw().getPart("file");
Part name = request.raw().getPart("name");
String filename = file.getName();
if(name.getSize() > 0){
try{
filename = IOUtils.toString(name.getInputStream(), StandardCharsets.UTF_8);
} catch(Exception e){
e.printStackTrace();
}
}
Path filePath = Paths.get(".",filename);
Files.copy(file.getInputStream(),filePath);
return "Done!";
});
}
I use postman to send the message
And I got the Error like this
The error points to the code Part file = request.raw().getPart("file");
post("/upload", "multipart/form-data", (request, response) -> {
String location = "image"; // the directory location where files will be stored
long maxFileSize = 100000000; // the maximum size allowed for uploaded files
long maxRequestSize = 100000000; // the maximum size allowed for multipart/form-data requests
int fileSizeThreshold = 1024; // the size threshold after which files will be written to disk
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(
location, maxFileSize, maxRequestSize, fileSizeThreshold);
request.raw().setAttribute("org.eclipse.jetty.multipartConfig",
multipartConfigElement);
Collection<Part> parts = request.raw().getParts();
for (Part part : parts) {
System.out.println("Name: " + part.getName());
System.out.println("Size: " + part.getSize());
System.out.println("Filename: " + part.getSubmittedFileName());
}
String fName = request.raw().getPart("file").getSubmittedFileName();
System.out.println("Title: " + request.raw().getParameter("title"));
System.out.println("File: " + fName);
Part uploadedFile = request.raw().getPart("file");
Path out = Paths.get("image/" + fName);
try (final InputStream in = uploadedFile.getInputStream()) {
Files.copy(in, out);
uploadedFile.delete();
}
// cleanup
multipartConfigElement = null;
parts = null;
uploadedFile = null;
return "OK";
});
This will work well, I found it in https://groups.google.com/forum/#!msg/sparkjava/fjO64BP1UQw/CsxdNVz7qrAJ

How to convert from org.apache.commons.net.ftp.FTPFile to String?

I'm retrieving files list from FTPClient using ftpClient.listFiles(); and it returns an array with correct file names and appropriate quantity.
I'm trying to read content from files, but only ftpClient.retrieveFileStream(fileName) is available for that purpose. And it somehow breaks after reading the first file and returns null.
Is there a way to convert FTPFile directly into String?
ftp.connect();
ftp.changeWorkingDirectoryToFrom();
List<String> idsList = new ArrayList<String>();
List<String> names = ftp.listFileNames();
for (String fileName : names) {
String content = fromFTPFileToString(fileName);
Matcher matcher = FILES_PATTERN.matcher(content);
String id = extractId(content);
if (matcher.find()) {
boolean duplicate = idsList.contains(id);
LOG.info("MATCHED: " + fileName);
if (!duplicate) {
ftp.moveFileFromTo(fileName);
idsList.add(id);
} else {
LOG.info("DUPLICATE: " + fileName);
duplicated++;
ftp.deleteFileOnFromFtp(fileName);
}
}
processed++;
}
ftp.disconnect();
private String fromFTPFileToString(String fileName) {
String content = "";
try {
InputStream is = ftp.readContentFromFTPFile(fileName);
StringWriter writer = new StringWriter();
IOUtils.copy(is, writer, ENCODING);
content = writer.toString();
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(writer);
} catch (Exception ex) {
LOG.error(ex);
}
return content;
}
void deleteFileOnFromFtp(String fileName) {
changeWorkingDirectory(properties.getProperty(PropertiesType.FOLDER_FROM.toString()));
deleteFile(fileName);
}
InputStream readContentFromFTPFile(String fileName) {
changeWorkingDirectory(properties.getProperty(PropertiesType.FOLDER_FROM.toString()));
InputStream inputStream = null;
try {
inputStream = ftpClient.retrieveFileStream(fileName);
} catch (IOException ex) {
LOG.error("Unable to extract content from file:" + O_Q + fileName + C_Q);
}
return inputStream;
}
void moveFileFromTo(String fileName) {
String from = FORWARD_SLASH + properties.getProperty(PropertiesType.FOLDER_FROM.toString()) + FORWARD_SLASH + fileName;
String to = FORWARD_SLASH + properties.getProperty(PropertiesType.FOLDER_TO.toString()) + FORWARD_SLASH + fileName;
try {
ftpClient.rename(from, to);
} catch (IOException ex) {
LOG.error("Unable to move file file from:" + O_Q + from + C_Q + " to: " + O_Q + to + C_Q);
throw new RuntimeException(ex.getCause());
}
}
3 Hints
1) You can use retrieveFile
And use a ByteArrayOutputStream as the 2nd parameter.
To get a String from it simply "new String(baos.toByteArray(),[The Charset you used]);"
2) Check for ftpClient.completePendingCommand();
If some commands are still pending
3) I had once a similar issue setting ftp.enterLocalPassiveMode() helped

losing data while writing through asynchronousFileChannel in java

I am trying to use asynchronousFileChannel to write the date into a text file. I made 3 jar file of the program with the AsynchronousFileChannel and compiled all 3 jars simultaneously through command prompt to read 3 different text files and output to one common temporary file
I have 2000 records in my test files(3) to be read,but the output in the common temporary file is missing some of the records,the output should have 6000 records but it shows only 5366 or 5666 or sometimes less than that.
I am not able to figure out why some data is lost as it is the functionality of a asynchronousFileChannel.
Here is the code for the java program using asynchronousfilechannel.
class Writer(){
public void writeOut(ReadableData fileData)
throws InterruptedException {
Path file = null;
AsynchronousFileChannel asynchFileChannel = null;
String filePath = tempFileName;
try {
file = Paths.get(filePath);
asynchFileChannel = AsynchronousFileChannel.open(file,
StandardOpenOption.WRITE, StandardOpenOption.CREATE);
CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {
#Override
public void completed(Integer result, Object attachment) {
if (result == Integer.MAX_VALUE) {
log.debug("Attachment: " + attachment + " " + result
+ " bytes written");
log.debug("CompletionHandler Thread ID: "
+ Thread.currentThread().getId());
}
result++;
}
#Override
public void failed(Throwable e, Object attachment) {
try {
throw e;
} catch (Throwable e1) {
e1.printStackTrace();
}
log.debug("File Write Failed Exception:");
e.printStackTrace();
}
};
String printData = fileData.getId() + "|"
+ fileData.getName() + "|" + fileData.getEmpId()
+ "|" + fileData.getServieId() + "|" + "\n";
asynchFileChannel.write(ByteBuffer.wrap(printData.getBytes()),
asynchFileChannel.size(), "file write", handler);
log.debug(printData);
}
}
catch (IOException e) {
e.printStackTrace();
log.error(e.getMessage());
} finally {
}
}
}
}
and this is my class to read data from 3 files:
public class FileReader1 {
static Logger log = Logger.getLogger(FileHandlerNorthBoundMain.class
.getName());
Writer wrO=new Writer();
public static void main(String[] args) throws IOException,
IllegalFileFormatException, InterruptedException {
String filePath = "C:\\Users\\Public\\testdata1.csv"; //"C:\\Users\\Public\\testdata2.csv"; "C:\\Users\\Public\\testdata3.csv";
File file = new File(filePath);
log.info("Fetching data.... from: " + filePath);
ArrayList<ReadableData> list = new ArrayList<ReadableData>();
FileInputStream fs = null;
BufferedReader reader = null;
String Name;
int Id, EmpId, ServiceId;
ReadableData readableData = null;
int count = 0;
fs = new FileInputStream(file);
reader = new BufferedReader(new InputStreamReader(fs));
String line = reader.readLine();
while (line != null) {
StringTokenizer st = new StringTokenizer(line, "\\|");
while (st.hasMoreTokens()) {
try {
Id = Integer.parseInt(st.nextToken());
Name = st.nextToken();
EmpId = Integer.parseInt(st.nextToken());
ServiceId = Integer.parseInt(st.nextToken());
readableData = new ReadableData(Id,
, Name, EmpId,ServiceId);
wrO.writeOut(readableData);
list.add(count, readableData);
count = count++;
} catch (Exception ex) {
log.error("Illegal File Format");
throw new IllegalFileFormatException("Illegal File Format");
}
}
line = reader.readLine();
}
reader.close();
}
Modify your Writer class with the following code part with asynchronousFileChannel lock()
byte[] test = printData.getBytes();
Future<FileLock> featureLock = asynchFileChannel.lock();
log.info("Waiting for the file to be locked ...");
FileLock lock = featureLock.get();
if (lock.isValid()) {
log.debug(printData);
Future<Integer> featureWrite = asynchFileChannel.write(
ByteBuffer.wrap(test), asynchFileChannel.size());
log.info("Waiting for the bytes to be written ...");
int written = featureWrite.get();
log.info("I’ve written " + written + " bytes into "
+ file.getFileName() + " locked file!");
lock.release();
}
This might be because asynchronousFileChannel is thread safe but Bytebuffer is not,care should be taken to ensure that the buffer is not accessed until after the operation has completed.
check the documentation http://openjdk.java.net/projects/nio/javadoc/java/nio/channels/AsynchronousFileChannel.html

Stream closed showing up in play framework 1.2.5

i have an application that want to write a file using fileoutputstream
here's the code, method patch
public static Response patch() {
try {
System.out.println("PATCH");
System.out.println(request.contentType);
String file = params.get("filename");
System.out.println("patch file: " + file);
Map<String, Header> MapOffset = request.headers;
for (Entry<String, Header> entry : MapOffset.entrySet()) {
System.out.println("Header['" + entry.getKey() + "]: "
+ entry.getValue().value());
}
Header offsetParam = MapOffset.get("offset");
Long offset = 0L;
if (offsetParam != null) {
offset = Long.parseLong(offsetParam.value());
}
InputStream input = request.body;
File f = new File(UPLOAD_DIR + System.getProperty("file.separator")
+ file);
System.out.println("address: " + f.getAbsolutePath());
System.out.println("offset: " + offset);
System.out.println("length: " + f.length());
fileBasicUpload(f, offset, input);
Response respon = new Response();
respon.status = OK;
return respon;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
and this is where i write a file
private static void fileBasicUpload(File f, Long offset, InputStream input)
throws IOException {
FileOutputStream output = null;
try {
int c = -1;
byte[] b = new byte[1024];
try {
output = new FileOutputStream(f, true);
while ((c = input.read(b)) != -1) {
output.write(b, 0, c);
}
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
} finally {
output.close();
}
}
but when my application called, then stream closed error is show up at while ((c = input.read(b)) != -1) that line.
i don't know how that error is called. sorry for my poor english and thanks
i found the answer. in my application i found like this
public static Response upload(File file){
System.out.println("Appliaction.upload");
response = ResumableUpload.post();
return response;
// render(response);
}
the parameter file, it must be delete, then it work!

Why all files in my application are written to jboss tmp directory?

I have function like this in my Bean:
public String uploadFile(UploadedFile uploadedFile) {
logger.info("Enter: uploadFile(UploadedFile uploadedFile).");
String name = uploadedFile.getName();
String extension = name.substring(name.length() - 3);
if (extension.contentEquals("peg")) {
extension = "jpeg";
}
RandomString rs = new RandomString(RANDOM_PHOTO_NAME_LENGTH);
this.randomPhotoName = rs.nextString();
String fileName = this.randomPhotoName + "." + extension;
logger.info("File name: " + name + ". Extension: " + extension + ". New fileName: " + fileName);
ServletContext sc = (ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext();
File f = new File(
sc.getRealPath(Constant.USER_FILE_PATH));
if (!f.exists()) {
logger.info("Folder "
+ Constant.USER_FILE_PATH
+ " nie istniej. Tworze nowy.");
f.mkdirs();
}
File backupFile = new File(
sc.getRealPath(Constant.USER_FILE_PATH
+ fileName));
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(uploadedFile.getInputStream());
out = new FileOutputStream(backupFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
} catch (IOException ioe) {
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage msg = null;
msg = new FacesMessage(
"Pojawił się nieoczekiwany błąd przy uploadowaniu pliku.");
context.addMessage(null, msg);
logger.error(
"Pojawił się nieoczekiwany błąd przy uploadowaniu pliku.",
ioe);
} finally {
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
logger.info("Exit: uploadFile(UploadedFile uploadedFile).");
return fileName;
}
And all files are saved in tmp directory eg:
\jboss-5.1.0.GA\server\default\tmp\a006-czo4uq-gzzu4l42-1-gzzuk7xr-a2\TupTus.war\media\img\user-gallery\6u2fpgu3tkzniwg.JPG
Because all your files are built as:
File backupFile = new File(
sc.getRealPath(Constant.USER_FILE_PATH
+ fileName));
Sounds like sc.getRealPath() returns working directory that JBoss allocates for your application.
So, the real question is to you: where do you want to write the files? If not there, so where? If you prefer user temporary directory use new File(System.getProperty("java.io.tmpdir"), fileName) and write there.
If you want to be able to configure the path out of the box you can store this path either in DB or configuration file or pass it via your custom system properties when you are running JBoss using command line switch -D.

Categories

Resources