why this exception FileItemStream$ItemSkippedException? - java

in a gwt web application.
I have to send a file and some parameter attached to it.
on ServerSide
try {
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iterator = upload.getItemIterator(request);
while (iterator.hasNext()) {
FileItemStream item = iterator.next();
if (item.isFormField()) {
String fieldName=item.getFieldName();
String fieldValue = Streams.asString(item.openStream());
System.out.println(" chk " +fieldName +" = "+ fieldValue);
} else {
stream = item.openStream();
fileName = item.getName();
mimetype = item.getContentType();
int c;
while ((c = stream.read()) != -1) {
System.out.print((char) c);
}
}
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
System.out.println("out of try");
ByteArrayOutputStream output = new ByteArrayOutputStream();
int nRead;
while ((nRead = stream.read(buffer, 0, buffer.length)) != -1) {
System.out.println("lenth111" +nRead);
output.write(buffer, 0, nRead);
}
System.out.println("lenth" +nRead);
output.flush();
with this code i can read the stream.
and also on console "out of try" is also printed
And finally on while ((nRead = stream.read(buffer, 0, buffer.length)) != -1)
line i got a Warning
WARNING: /UploadFileServlet: org.apache.commons.fileupload.FileItemStream$ItemSkippedException.
How to solve this problem.??

Answer a bit late but I had the same problem.
Why you get that exception: The JavaDocs of ItemSkippedException explain a little bit:
This exception is thrown, if an attempt is made to read data from the InputStream, which has been returned by FileItemStream.openStream(), after Iterator.hasNext() has been invoked on the iterator, which created the FileItemStream.
You are using the InputStream stream outside the while loop which causes the problem because another iteration is called which closes (skips) the file InputStream you try to read from.
Solution: Use the InputStream inside the while loop. If you need all form-fields before processing the file, ensure you set it in the right order on client side. First all fields, last the file. For example using the JavaScript FormData:
var fd = new window.FormData();
fd.append("param1", param1);
fd.append("param2", param2);
// file must be last parameter to append
fd.append("file", file);
And on server side:
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
InputStream stream = item.openStream();
// the order of items is given by client, first form-fields, last file stream
if (item.isFormField()) {
String name = item.getFieldName();
String value = Streams.asString(stream);
// here we get the param1 and param2
} else {
String filename = item.getName();
String mimetype = item.getContentType();
ByteArrayOutputStream output = new ByteArrayOutputStream();
int nRead;
while ((nRead = stream.read(buffer, 0, buffer.length)) != -1) {
System.out.println("lenth111" +nRead);
output.write(buffer, 0, nRead);
}
System.out.println("lenth" +nRead);
output.flush();
}
}

I had the same issue. To solve it, I had to break out of the while loop after reading the last item:
import java.io.InputStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
final String ID = "id";
final String FILE_NAME = "fileName";
final String APIKEY = "apikey";
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
String id = null;
String apikey = null;
String fileName = null;
InputStream stream = null;
FileItemIterator iterator = upload.getItemIterator(request);
outer: while (iterator.hasNext()) {
FileItemStream item = iterator.next();
switch (item.getFieldName()) {
case ID:
id = Streams.asString(item.openStream());
break;
case APIKEY:
apikey = Streams.asString(item.openStream());
break;
case FILE_NAME:
fileName = item.getName();
stream = item.openStream();
break outer;
}
}
break outer; is the line that solved my issue.

Related

Sound distortion when extracting from Jar

I have sounds in my jar file directory.
I need to use these sounds and I am trying to extract them using this method:
String charset = "ISO-8859-1";
public void extractSounds(String pathIn, String pathOut) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(pathIn), charset));
String line = r.readLine();
String result = null;
FileOutputStream fos = new FileOutputStream(pathOut);
while(line != null) {
if(result != null) {
result += "\r" + line;
line = r.readLine();
} else {
result = line;
line = r.readLine();
}
}
fos.write(result.getBytes(charset));
}}
But when I extract the sounds they get distorted and I don't know what the problem is, because it basically just copies the file.
Sounds:
Original,
Extracted
I would be very grateful if you could help me find a solution or suggest another method to extract the sound files.
Don't assume you are reading text. You should not try to mutate the data. Just copy it in chunks.
Try something like
InputStream in = ...;
ByteArrayOutputStream out = new ByteArrayOutputStream();
final int BUF_SIZE = 1 << 8;
byte[] buffer = new byte[BUF_SIZE];
int bytesRead = -1;
while((bytesRead = in.read(buffer)) > -1) {
out.write(buffer, 0, bytesRead);
}

Java - Vaadin - Table not filling

little bit of a pickle here. I am reading a JSON From a Zip file and I want to fill a table in Vaadin with the contents of the JSON.
Here's my Function to read the stuff and fill the table, this is Java.
private void getJsonContent() {
try {
FileInputStream fis = new FileInputStream(backupFile);
ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
byte[] buffer = new byte[1024];
while((entry = zin.getNextEntry()) != null) {
if(entry.getName().equalsIgnoreCase("content.json")) {
int n;
while((n = zin.read(buffer, 0, 1024)) > -1){
String JSON = new String(buffer, Charset.forName("UTF-8"));
JSONObject obj = new JSONObject(JSON);
logger.info(JSON);
// Assign "global" Values to Variables
this.createdAt = obj.getString("created_at");
this.version = obj.getString("version");
// Fill table if applicable
for(int i = 0; i < obj.getJSONArray("content").length(); i++) {
JSONObject sub = obj.getJSONArray("content").getJSONObject(i);
logger.info(sub);
infoTable.addItem(new Object[] {
sub.get("imported_identities").toString(),
sub.get("project_versions").toString(),
sub.get("last_import").toString(),
sub.get("client").toString(),
sub.get("project").toString()
}, i +1);
}
}
}
}
zin.close();
fis.close();
} catch (FileNotFoundException e) {
// Can't happen here
} catch (IOException e) {
logger.info("Can't read File.");
} catch (JSONException jse) {
logger.info("JSON Content could not be read: " + jse.getMessage());
}
}
You will notice I have a function call logger.info(sub) - to make sure what I get is another valid JSON Object (the file I am reading contains nested things)
Output:
{"imported_identities":0,"project_versions":0,"last_import":null,"client":"Client1","project":"Project2"}
{"imported_identities":0,"project_versions":0,"last_import":null,"client":"Client2","project":"Project1"}
{"imported_identities":0,"project_versions":1,"last_import":"2016-09-14T09:28:24.520Z","client":"Client1","project":"Project1"}
I made sure all the values were correct (and the table is built with null as default) - here is the table properties:
infoTable.addContainerProperty(impIds, String.class, null);
infoTable.addContainerProperty(projVe, String.class, null);
infoTable.addContainerProperty(lstImp, String.class, null);
infoTable.addContainerProperty(client, String.class, null);
infoTable.addContainerProperty(projct, String.class, null);
infoTable.setColumnCollapsingAllowed(true);
infoTable.setColumnCollapsed(impIds, true);
infoTable.setColumnCollapsed(projVe, true);
infoTable.setColumnCollapsed(lstImp, true);
Finally, the table has "refreshRowCache" called on it. Anyone see the problem? There are no errors, no nothing, the table just doesn't add the item (the size of infoTable.getItemIds().size() is 0 right after the call.
EDIT:
I tried the following to verify.
infoTable.addItem(i + 1);
infoTable.getItem(i + 1).getItemProperty(impIds).setValue(sub.get("imported_identities").toString());
infoTable.getItem(i + 1).getItemProperty(projVe).setValue(sub.get("project_versions").toString());
This went and caused a NullPointerException, the stack trace however does not contain any of my classes as far as I can see.
The following is wrong:
The String constructor needs the read size (n).
while ((n = zin.read(buffer, 0, 1024)) > -1) {
String JSON = new String(buffer, 0, n, StandardCharsets.UTF_8);
Then you do JSONs of at most 1024 in the loop, instead on one JSON of it all
The bytes of a UTF-8 cannot be split at some point say at position 1024 and expect to have a valid complete multi-byte sequence at end and following block's begin.
Also there is readFully and closeEntry was missing.
In short:
private void getJsonContent() {
try (ZipInputStream zin = new ZipInputStream(new BufferedInputStream(
new FileInputStream(backupFile)))) {
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) {
if (entry.getName().equalsIgnoreCase("content.json")) {
long size = entry.getSize();
if (size > 100_000) {
throw new IllegalArgumentException("Data too large");
}
// We could use an InputStreamReader and read text piecewise.
// However JSON parsing also is easiest on an entire text.
byte[] buffer = new byte[(int)size];
int n = zin.readFully(buffer, 0, buffer.length);
String json = new String(buffer, StandardCharsets.UTF_8);
JSONObject obj = new JSONObject(json);
logger.info(json);
// Assign "global" Values to Variables
this.createdAt = obj.getString("created_at");
this.version = obj.getString("version");
// Fill table if applicable
for (int i = 0; i < obj.getJSONArray("content").length(); i++) {
JSONObject sub = obj.getJSONArray("content").getJSONObject(i);
logger.info(sub);
infoTable.addItem(new Object[] {
sub.get("imported_identities").toString(),
sub.get("project_versions").toString(),
sub.get("last_import").toString(),
sub.get("client").toString(),
sub.get("project").toString()
}, i + 1);
}
} // if
zin.closeEntry(); // Do not forget preparing for the next entry
}
} catch (IOException e) {
logger.info("Can't read File.");
} catch (JSONException jse) {
logger.info("JSON Content could not be read: " + jse.getMessage());
}
}
The try-with-resources closes automatically even on exception or return.

java zip to binary format and then decompress

I have a task that
read a zip file from local into binary message
transfer binary message through EMS as String (done by java API)
receive transferred binary message as String (done by java API)
decompress the binary message and then print it out
The problem I am facing is DataFormatException while decompress the message.
I have no idea which part went wrong.
I use this to read file into binary message:
static String readFile_Stream(String fileName) throws IOException {
File file = new File(fileName);
byte[] fileData = new byte[(int) file.length()];
FileInputStream in = new FileInputStream(file);
in.read(fileData);
String content = "";
System.out.print("Sent message: ");
for(byte b : fileData)
{
System.out.print(getBits(b));
content += getBits(b);
}
in.close();
return content;
}
static String getBits(byte b)
{
String result = "";
for(int i = 0; i < 8; i++)
result = ((b & (1 << i)) == 0 ? "0" : "1") + result;
return result;
}
I use this to decompress message:
private static byte[] toByteArray(String input)
{
byte[] byteArray = new byte[input.length()/8];
for (int i=0;i<input.length()/8;i++)
{
String read_data = input.substring(i*8, i*8+8);
short a = Short.parseShort(read_data, 2);
byteArray[i] = (byte) a;
}
return byteArray;
}
public static byte[] unzipByteArray(byte[] file) throws IOException {
byte[] byReturn = null;
Inflater oInflate = new Inflater(false);
oInflate.setInput(file);
ByteArrayOutputStream oZipStream = new ByteArrayOutputStream();
try {
while (! oInflate.finished() ){
byte[] byRead = new byte[4 * 1024];
int iBytesRead = oInflate.inflate(byRead);
if (iBytesRead == byRead.length){
oZipStream.write(byRead);
}
else {
oZipStream.write(byRead, 0, iBytesRead);
}
}
byReturn = oZipStream.toByteArray();
}
catch (DataFormatException ex){
throw new IOException("Attempting to unzip file that is not zipped.");
}
finally {
oZipStream.close();
}
return byReturn;
}
The message I got is
java.io.IOException: Attempting to unzip file that is not zipped.
at com.sourcefreak.example.test.TibcoEMSQueueReceiver.unzipByteArray(TibcoEMSQueueReceiver.java:144)
at com.sourcefreak.example.test.TibcoEMSQueueReceiver.main(TibcoEMSQueueReceiver.java:54)
After check, the binary message does not corrupted after transmission.
Please help to figure out the problem.
Have you tried using InflaterInputStream? Based on my experience, using Inflater directly is rather tricky. You can use this to get started:
public static byte[] unzipByteArray(byte[] file) throws IOException {
InflaterInputStream iis = new InflaterInputStream(new ByteArrayInputStream(file));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[512];
int length = 0;
while ((length = iis.read(buffer, 0, buffer.length) != 0) {
baos.write(buffer, 0, length);
}
iis.close();
baos.close();
return baos.toByteArray();
}
I finally figure out the problem.
The problem is the original file is a .zip file, so I should use zipInputStream to unzip the file before further processing.
public static byte[] unzipByteArray(byte[] file) throws IOException {
// create a buffer to improve copy performance later.
byte[] buffer = new byte[2048];
byte[] content ;
// open the zip file stream
InputStream theFile = new ByteArrayInputStream(file);
ZipInputStream stream = new ZipInputStream(theFile);
ByteArrayOutputStream output = new ByteArrayOutputStream();
try
{
ZipEntry entry;
while((entry = stream.getNextEntry())!=null)
{
//String s = String.format("Entry: %s len %d added %TD", entry.getName(), entry.getSize(), new Date(entry.getTime()));
//System.out.println(s);
// Once we get the entry from the stream, the stream is
// positioned read to read the raw data, and we keep
// reading until read returns 0 or less.
//String outpath = outdir + "/" + entry.getName();
try
{
//output = new FileOutputStream(outpath);
int len = 0;
while ((len = stream.read(buffer)) > 0)
{
output.write(buffer, 0, len);
}
}
finally
{
// we must always close the output file
if(output!=null) output.close();
}
}
}
finally
{
// we must always close the zip file.
stream.close();
}
content = output.toByteArray();
return content;
}
This code work for zip file containing single file inside.

Process binary file in Java using FileItemStream

I have a webapplication which allows to upload binary files. I have to parse them and save the content 1:1 into a String and then into the database.
When I use uuencode on a unix machine to encode the binary file, then it works. Is there a way to do this automatically in java?
if (isMultipart) {
//Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();
//Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (!item.isFormField()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;
licenseString = "";
while ((line = reader.readLine()) != null) {
System.out.println(line);
// Generate License File
licenseString += line + "\n";
}
}
}
session.setAttribute("licenseFile", licenseString);
System.out.println("adding licensestring to session. ");
}
It works of course for all non-binary files uploaded. How can I extend it to support binary files?
// save to file
// =======================================
InputStream is = new BufferedInputStream(item.openStream());
BufferedOutputStream output = null;
try {
output = new BufferedOutputStream(new FileOutputStream("temp.txt", false));
int data = -1;
while ((data = is.read()) != -1) {
output.write(data);
}
} finally {
is.close();
output.close();
}
// read content of file
// =======================================
System.out.println("content of file:");
try {
FileInputStream fstream = new FileInputStream("temp.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
licenseString = "";
String strLine;
while ((strLine = br.readLine()) != null) {
System.out.println(javax.xml.bind.DatatypeConverter.printBase64Binary(strLine.getBytes()));
licenseString += javax.xml.bind.DatatypeConverter.printBase64Binary(strLine.getBytes()) + "\n";
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
You could use the commons_fileupload lib (check it here : org.apache.commons.fileupload.disk.DiskFileItem is not created properly?)
The doc is here : http://commons.apache.org/fileupload/using.html
Your case is pretty well explained on the official website.
A Better way would be to write the upload to a temporary file and then handle it from there:
if (!item.isFormField()) {
InputStream stream = new BufferedInputStream(item.getInputStream());
BufferedOutputStream output = null;
try {
output = new BufferedOutputStream(new FileOutputStream(your_temp_file, false));
int data = -1;
while ((data = input.read()) != -1) {
output.write(data);
}
} finally {
input.close();
output.close();
}
}
now you have a temporary file, which is the same as the uploaded file, you can do your 'other' calculations from there.

Uploading Image From Java Desktop App to Server

I am using the following code on the client side to upload to the server
public class UploaderExample{
private static final String Boundary = "--7d021a37605f0";
public void upload(URL url, List<File> files) throws Exception
{
HttpURLConnection theUrlConnection = (HttpURLConnection) url.openConnection();
theUrlConnection.setDoOutput(true);
theUrlConnection.setDoInput(true);
theUrlConnection.setUseCaches(false);
theUrlConnection.setChunkedStreamingMode(1024);
theUrlConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary="
+ Boundary);
DataOutputStream httpOut = new DataOutputStream(theUrlConnection.getOutputStream());
for (int i = 0; i < files.size(); i++)
{
File f = files.get(i);
String str = "--" + Boundary + "\r\n"
+ "Content-Disposition: form-data;name=\"file" + i + "\"; filename=\"" + f.getName() + "\"\r\n"
+ "Content-Type: image/png\r\n"
+ "\r\n";
httpOut.write(str.getBytes());
FileInputStream uploadFileReader = new FileInputStream(f);
int numBytesToRead = 1024;
int availableBytesToRead;
while ((availableBytesToRead = uploadFileReader.available()) > 0)
{
byte[] bufferBytesRead;
bufferBytesRead = availableBytesToRead >= numBytesToRead ? new byte[numBytesToRead]
: new byte[availableBytesToRead];
uploadFileReader.read(bufferBytesRead);
httpOut.write(bufferBytesRead);
httpOut.flush();
}
httpOut.write(("--" + Boundary + "--\r\n").getBytes());
}
httpOut.write(("--" + Boundary + "--\r\n").getBytes());
httpOut.flush();
httpOut.close();
// read & parse the response
InputStream is = theUrlConnection.getInputStream();
StringBuilder response = new StringBuilder();
byte[] respBuffer = new byte[4096];
while (is.read(respBuffer) >= 0)
{
response.append(new String(respBuffer).trim());
}
is.close();
System.out.println(response.toString());
}
public static void main(String[] args) throws Exception
{
List<File> list = new ArrayList<File>();
list.add(new File("C:\\square.png"));
list.add(new File("C:\\narrow.png"));
UploaderExample uploader = new UploaderExample();
uploader.upload(new URL("http://systemout.com/upload.php"), list);
}
}
I have tried writing the servlet that receives the image file and saves it to a folder on the server....but have failed miserably...This is part of an academic project i need to submit as part of my degree....Please Help!!!
I want help ...can someone guide me on how the servlet will be written....
I tried the following:
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
InputStream input = null;
OutputStream output = null;
try {
input = request.getInputStream();
output = new FileOutputStream("C:\\temp\\file.png");
byte[] buffer = new byte[10240];
for (int length = 0; (length = input.read(buffer)) > 0 ; ) {
output.write(buffer, 0, length);
}
}
catch(Exception e){
out.println(e.getMessage());
}
finally {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
}
out.println("Success");
}
catch(Exception e){
out.println(e.getMessage());
}
finally {
out.close();
}
}
I went ahead and tried the fileupload from apache.org....and wrote the following servlet code:
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println(1);
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List /* FileItem */ items = upload.parseRequest(request);
// Process the uploaded items
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
//processFormField(item);
} else {
//processUploadedFile(item);
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
//write to file
File uploadedFile = new File("C:\\temp\\image.png");
item.write(uploadedFile);
out.println("Sucess!");
}
}
} else {
out.println("Invalid Content!");
}
} catch (Exception e) {
out.println(e.getMessage());
} finally {
out.close();
}
}
However i am still confused on how to write the multipart code on the client side...the one i posted above is not working with my servlet implementation.....help please....some links where i can learn writing posting multipart form from java desktop app would be useful
So here's my recommendation: don't write this code yourself! Use http://commons.apache.org/fileupload/ instead. It will save you a lot of headaches, and you'll be up and running quite quickly. I'm pretty sure that problem is that the InputStream contains the multi-part boundaries, and is thus not a valid image.
Here's another observation: since you're not doing any transformations on the image, there's no need to read and write the image bytes using ImageIO. You're better off writing the bytes straight from the InputStream to the file.

Categories