How to convert OutputStream to String in Java (Android)? - java

I am trying to read the string that I get inside an outputStream that in turn is written there by a ftp - from a ftp server.
I'm stuck at this problem for about 2 hours and I find it hard to belive that it's so difficult to solve.
Is there any nice solution for my problem?
Here's the relevant code:
boolean success = false;
OutputStream outputStream = null;
try {
outputStream = new BufferedOutputStream(new FileOutputStream(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + fileName));
success = ftp.retrieveFile("/ViatorAndroid/" + fileName, outputStream);
} catch (Exception e) {
Log.d("FTPDownloadLatestVersion", "e = " + e.getMessage() + " " + Arrays.toString(e.getStackTrace()));
}
outputStream.close();
if (success) {
String versionNumberString = outputStream.getString(); // ??? I need here a way to get the string inside this output stream. Any clue how???
int versionNumber = Integer.parseInt(versionNumberString);
Log.d("FTPGetLastestVersionCode", "VersionNumber = " + versionNumber);
return BuildConfig.VERSION_CODE < versionNumber;
}

If you just want the content in a string, you build a ByteArrayOutputStream that will collect all the bytes written to it, and then turn this into a String.
Something like
try (ByteArrayOutputStream baos=new ByteArrayOutputStream()){
boolean success = ftp.retrieveFile("/ViatorAndroid/" + fileName, baos);
if (success){
String versionNumberString = new String(baos.toByteArray(),StandardCharsets.UTF_8);
...
}
}

Related

android studio inputStream form URL problem

I'm using this code for bypass the css from WebView loading , I used asset folder for loading my own css but now I need to load my custom css from URL because I need to Change my Css every week .
probelm is : after change InputStream to URL my css bypass is note working !!
My old code is :
private void injectCSS() {
try {
InputStream inputStream = getAssets().open("style.css");
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
webView.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var style = document.createElement('style');" +
"style.type = 'text/css';" +
// Tell the browser to BASE64-decode the string into your script !!!
"style.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(style)" +
"})()");
} catch (Exception e) {
e.printStackTrace();
}
}
and My New code is : > but is not working
private void injectCSS() {
try {
final InputStream inputStream = new URL("https://sitemname.ir/app/style.css").openStream();
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
webView.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var style = document.createElement('style');" +
"style.type = 'text/css';" +
// Tell the browser to BASE64-decode the string into your script !!!
"style.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(style)" +
"})()");
} catch (Exception e) {
e.printStackTrace();
}
}

What is the accurate way to read/download a file from the server (in Java)?

In my client-server application I have used a command (GET filename)to download a file into the client side. I have used the build in read() method to read the file. My teachers said it's not a very good practice to implement this read method. The reason is either it doesn't tell how exactly the file is reading from the server or it somehow is not able to download dynamic (large) file size. But at the moment I see that it's working fine. Since I am still in intermediate level in java, I need to learn the best way to do this job. How it could be improved in coding? That is I want to improve the while looping part in ClientSide.
I have pasted the relevent code:
ClientSide:
............
............
if (request.startsWith("GET")) {
File file = new File(request.substring(4));
is = socket.getInputStream();
fos = new FileOutputStream(file);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
int bytesReceived = 0;
while ((bytesReceived = is.read(buffer)) >=0) {
//while ((bytesReceived = is.read(buffer))>=buffer) {
fos.write(buffer, 0, bytesReceived);
}
request = "";
fos.close();
is.close();
}
.................
.................
ServerSide:
.................
.................
else if (request.startsWith("GET")) {
System.out.println("");
String filename = request.substring(4);
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
if (fileExists(files, filename)) {
file = new File(filename);
int fileSize = (int) file.length();
outputToClient.print("Status OK\r\n"
+ "Size " + fileSize + "KB" + "\r\n"
+ "\r\n"
+ "File " + filename + " Download was successfully\r\n");
outputToClient.flush();
// reading files
fis = new FileInputStream(file);
os = socket.getOutputStream();
byte[] buffer = new byte[2^7-1];
int bytesRead = 0;
while ((bytesRead = fis.read(buffer))!= -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
fis.close();
} else {
outputToClient.print("Status 400\r\n"
+ "File " + filename + " not found\r\n"
+ "\r\n");
outputToClient.flush();
}
}
outputToClient.flush();
}
.................
.................
You need to consume the rest of the HTTP response headers, by reading until you get a blank line, if you haven't already done that.
Apart from that, your code looks fine to me, except that I would use a much bigger buffer than 127, at least 8192, possibly a multiple of that.
Ask your teacher what (on earth) he's talking about.

Writing a contact's photo into a vcf file, android

I am using a code in which a list of all contacts is shown. When I select a contact from the list, details of the contact are shown and saved in a .vcf file (in proper vcard format), working fine. when I select a contact which has a photo as well, it shows the photo in imageView, but I don't know how to write the photo in vcf file.
I have used these lines,
Uri photoUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,Integer.parseInt(item));
Bitmap photoBitmap;
ContentResolver cr = getContentResolver();
InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(cr, photoUri);
photoBitmap = BitmapFactory.decodeStream(is);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
photoBitmap.compress(CompressFormat.JPEG, 100 , bos);
byte[] bitmapdata = bos.toByteArray();
imageEncoded = Base64.encodeToString(bitmapdata,Base64.DEFAULT);
String content = "BEGIN:VCARD\nVERSION:3.0\nCLASS:PUBLIC\nPRODID:-//class_vcard from TroyWolf.com//NONSGML Version 1//EN\nFN:"+contactName+"\nTEL;TYPE=cell,voice:"+number+"\nPHOTO;TYPE=JPEG;ENCODING=BASE64:"+imageEncoded+"\nTZ:+0000\nEND:VCARD";
But I am getting error while reading the contact("Failed to parse vCard for unexpected reason, Invalid line:")
Can anyone please help me solve the problem!
Try changing the value of the ENCODING parameter from BASE64 to B. B is the correct value to use in 3.0 vCards.
Also, the correct newline sequence for vCards is \r\n, not \n.
You might be interested in using a vCard library to generate your vCard. ez-vcard is one such library (disclaimer: I am the author).
VCard vcard = new VCard();
vcard.setClassification("PUBLIC");
vcard.setProdId("-//class_vcard from TroyWolf.com//NONSGML Version 1//EN");
vcard.setFormattedName(contactName);
TelephoneType tel = vcard.addTelephoneNumber(number);
tel.addType(TelephoneTypeParameter.CELL);
tel.addType(TelephoneTypeParameter.VOICE);
PhotoType photo = new PhotoType(bitmapdata, ImageTypeParameter.JPEG);
vcard.addPhoto(photo);
vcard.setTimezone(new TimezoneType(0, 0));
String content = Ezvcard.write(vcard).version(VCardVersion.V3_0).prodId(false).go();
This is a really late post, but I couldn't find any working solution on StackOverflow without using the library, so I thought it would be good to share my findings.
Changing the encoding parameter and correcting a newline sequence weren't enough to construct .vcf file with a photo. I also had to remove the line breaks after encoding to base64.
Sample code to convert Uri to base64 format (replace imageStream initialization as needed).
// string you can use to write to vcf file (3.0 vCards)
String.format("PHOTO;ENCODING=B;TYPE=JPEG: ,%s\r\n", convertUriToBase64(context, photoUri));
private String convertUriToBase64(Context context, String photoUri) {
InputStream imageStream = null;
try {
imageStream = context.getContentResolver().openInputStream(Uri.parse(photoUri));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] bitmapData = bos.toByteArray();
// line break has to be removed, so it is on the same line as PHOTO
return Base64.encodeToString(bitmapData, Base64.DEFAULT).replaceAll("\n", "");
}
Here's what I did to get a photo to send as part of the vCard...
Important things to consider:
1) Equipment: ZTE Axon 7 running Android 6.01
2) Couldn't get vCard 3.0 or 4.0 to function properly, could only use vCard 2.1
File vcfFile = new File(DisplayContactActivity.this.getExternalFilesDir(null), "generated.vcf");
try
{
/**Only Version 2.1 worked for me with or without PHOTO**/
FileWriter fw = new FileWriter(vcfFile);
fw.write("BEGIN:VCARD\r\n");
fw.write("VERSION:2.1\r\n");
fw.write("FN:" + "Contact 7" + "\r\n");
/*Getting the name of the File as I had saved it*/
String file_name = ("current_contact_image" + CONTACT_ID);
/*Get the bitmap that we stored in a File*/
Bitmap bitmap = getContactImage(file_name);
/*Convert bitmap to Base64*/
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String image_encoded = Base64.encodeToString(b, Base64.DEFAULT);
/*Write the encoded version of image to vCard 2.1, NOTICE that no determining whether the image is GIF or JPEG is needed*/
fw.write("PHOTO;ENCODING=BASE64:" + image_encoded + "\r\n");
/*Write some other stuff to the vCard also just trying to give whoever needs this a starting point*/
fw.write("TEL;Primary:" + "(586) 268-3437" + "\r\n");
fw.write("TEL;OTHER:" + "(313) 313-4545" + "\r\n");
fw.write("ADR;OTHER:" + "12345 AnyLane Dr." + "\r\n");
fw.write("ADR;OTHER:" + "54321 AnyPlace Av." + "\r\n");
fw.write("EMAIL;OTHER:" + "email#yahoo.com" + "\r\n");
fw.write("EMAIL;OTHER:" + "email#wowway.com" + "\r\n");
fw.write("END:VCARD\r\n");
fw.close();
Intent i = new Intent();
i.setAction(android.content.Intent.ACTION_VIEW);
i.setDataAndType(Uri.fromFile(vcfFile), "text/x-vcard");
startActivity(i);
}
catch (Exception e)
{
Log.i(TAG, "Exception: " + e);
}
public Bitmap getContactImage(String file_name)
{
Log.i(TAG, "Running getContactImage() with file name: " + file_name);
Bitmap thumbnail = null;
//------------------------------------------------------------------------------------------
try
{
File filePath = getBaseContext().getFileStreamPath(file_name);
FileInputStream fis = new FileInputStream(filePath);
thumbnail = BitmapFactory.decodeStream(fis);
}
catch (Exception e) //Use scaled_bitmap_for_storage instead of the current_contact_image file name
{
/*Error getting user-selected image, set boolean to get default image*/
Log.i(TAG, "Exception while running getContactImage() for file name: " + file_name + " with error message: " + e);
}
//------------------------------------------------------------------------------------------
return thumbnail;
}

How to disable buffering in Java HttpURLConnection for multi-part form post?

(This is for a signed applet and I have decided against HTTPClient to keep my jar very small)
I am using HttpURLConnection to successfully upload a file from the user to a server using multi-part form post.
The problem is that HttpURLConnection is caching the data -- before sending it. So when I am reading from the file and writing to Outputstream, it is merely buffering the data -- and therefore my progress bar, that shows the upload status , is completely wrong. Howevere please note that the form post code works and the file does get uploaded correctly with return code of 200.
So how do I ensure that HttpURLConnection does not cache the data that I am sending to the server ?
Here is my source:
public UploadResponse send(String formPostUrlStr,String fileFieldName,File targetFile, Map<String, String> valuesMap, UploadStatusListener uploadStatusListener) throws Exception{
String sendStr=getBoundaryMessage(Boundary, valuesMap, fileFieldName, targetFile.getName(), valuesMap.get("content-type") );//"image/png") ;
System.out.println(" multi-part start \n "+ sendStr+ " multi-part end \n");
String lenstr=Long.toString((long)(sendStr.length()*2)+ targetFile.length());
System.out.println("Content-Length"+ lenstr);
//Content-Length
URL url= new URL(formPostUrlStr);
long startTime= System.currentTimeMillis();
HttpURLConnection s3Connection = (HttpURLConnection) url.openConnection();
System.out.println("opened url to "+ formPostUrlStr +", connection ok ..");
s3Connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="
+ Boundary);
s3Connection.setRequestProperty("content-length", lenstr);
s3Connection.setDoOutput(true);
s3Connection.setDoInput(true);
s3Connection.setUseCaches(false);
s3Connection.setInstanceFollowRedirects(true);
s3Connection.setAllowUserInteraction(true);
s3Connection.setRequestProperty("User-Agent", "Mozilla/4.5");
if (uploadStatusListener != null) {
uploadStatusListener.statusUpdate(targetFile.length(), 0);
}
String debugStr= s3Connection.toString();
System.out.println("conmnection "+ debugStr);
DataOutputStream httpOut = new DataOutputStream(s3Connection.getOutputStream());
System.out.println("opened DataOutputStream ok ..");
httpOut.write(sendStr.getBytes());
//httpOut.flush();
System.out.println("httpOut.flush 1 ok ..");
FileInputStream uploadFileReader = new FileInputStream(targetFile);
long totalBytes = uploadFileReader.available();
if (uploadStatusListener != null) {
uploadStatusListener.statusUpdate(totalBytes, 0);
}
System.out.println(" uploading file with size "+ uploadFileReader.available());
int bufSize = 102400;
long availableBytesToRead;
long totalSent = 0;
while ((availableBytesToRead = uploadFileReader.available()) > 0) {
byte[] bufferBytesRead;
bufferBytesRead = availableBytesToRead >= bufSize ? new byte[bufSize]
: new byte[(int)availableBytesToRead];
int count = uploadFileReader.read(bufferBytesRead);
try{
httpOut.write(bufferBytesRead);
totalSent += ((long) count);
System.out.println(" wrote bytes = "+count+ ", total sent = "+ totalSent +", pendingSize"+ (availableBytesToRead-count) );
}
catch(IOException ioe){
System.out.println(" io exceotion e"+ ioe.getMessage());
throw ioe;
}
//httpOut.flush();
if (uploadStatusListener != null) {
uploadStatusListener.statusUpdate(totalBytes, totalSent);
}
}
// FILE DATA END
httpOut.write(("--" + Boundary + "--\r\n").getBytes());
// form end
httpOut.write(("--" + Boundary + "--\r\n").getBytes());
httpOut.flush();
httpOut.close();
long endTime= System.currentTimeMillis();
System.out.println("Completed Writing Data to S3 Connection in "+ (endTime-startTime)+"ms.,now waiting for rsponse code ");
int code=s3Connection.getResponseCode();
long endTime2= System.currentTimeMillis();
System.out.println("Completed Sendind Data to S3 in "+ (endTime2-startTime)+ "ms., rsponse code time "+ (endTime2-endTime)+"ms. ");
UploadResponse uploadResponse = new UploadResponse();
uploadResponse.setCode(code);
System.out.println(" response code : " + code);
StringBuilder response = new StringBuilder();
byte[] respBuffer = new byte[4096];
if (code > 300) {
if (code == 404) {
throw new Exception("Error 404");
}
BufferedReader err = new BufferedReader(
new InputStreamReader(s3Connection.getErrorStream()));
String ret;
StringBuffer buff = new StringBuffer();
while ((ret = err.readLine()) != null) {
buff.append(ret);
}
uploadResponse.setMessage(buff.toString());
System.out.println(" error :"+ buff.toString());
err.close();
} else {
BufferedReader inp = new BufferedReader(
new InputStreamReader(s3Connection.getInputStream()));
StringBuffer buff = new StringBuffer();
String ret;
while ((ret = inp.readLine()) != null) {
buff.append(ret);
}
inp.close();
uploadResponse.setMessage(buff.toString());
if(buff.toString().contains("fail"))
throw new Exception("Upload failed");
}
System.out.println(response.toString());
return uploadResponse;
}
}
I have the same problem.
I didn't find any other solution than writing my HTTP request on a raw Socket.
Did you find a better workaround ?
EDIT : I just did : we just have to use obj.setFixedLengthStreamingMode(12345) on the HttpURLConnection object obtained from url.openConnection(), where 12345 is the length of POST request body.
As a complementation for the answer that #Antares gave, there is another method setChunkedStreamingMode that is used when you don't know the content size in advance. So when you do a POST request, call that method on the connection:
HttpURLConnection connection = ...
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setChunkedStreamingMode(0);
connection.connect();
... connection.getOutputStream();
This will avoid the OutputStream to buffer the entire content before start to send.

file upload using java servlet as a service without a web browser

I am very new to java and servlet programming.
I am not sure whether it is possible to write a servlet which when passed a URL from the local client machine, uploads the file to the server.
basically on the client machine we have a C# program and on the server side we have Apache-tomcat installed. I need to upload file(s) to the server using C# program on client machine.
Should I provide any more information (?)
Thanks in Advance
Note this code illustrates the general idea and not guaranteed to work without modification.
The C# file upload part
// this code shows you how the browsers wrap the file upload request, you still can fine a way simpler code to do the same thing.
public void PostMultipleFiles(string url, string[] files)
{
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest.Method = "POST";
httpWebRequest.KeepAlive = true;
httpWebRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream memStream = new System.IO.MemoryStream();
byte[] boundarybytes =System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary +"\r\n");
string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";
memStream.Write(boundarybytes, 0, boundarybytes.Length);
for (int i = 0; i < files.Length; i++)
{
string header = string.Format(headerTemplate, "file" + i, files[i]);
//string header = string.Format(headerTemplate, "uplTheFile", files[i]);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(files[i], FileMode.Open,
FileAccess.Read);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
memStream.Write(boundarybytes, 0, boundarybytes.Length);
fileStream.Close();
}
httpWebRequest.ContentLength = memStream.Length;
Stream requestStream = httpWebRequest.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
try
{
WebResponse webResponse = httpWebRequest.GetResponse();
Stream stream = webResponse.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string var = reader.ReadToEnd();
}
catch (Exception ex)
{
response.InnerHtml = ex.Message;
}
httpWebRequest = null;
}
and to understand how the above code was written you might wanna take a look at How does HTTP file upload work?
POST /upload?upload_progress_id=12344 HTTP/1.1
Host: localhost:3000
Content-Length: 1325
Origin: http://localhost:3000
... other headers ...
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryePkpFF7tjBAqx29L
------WebKitFormBoundaryePkpFF7tjBAqx29L
Content-Disposition: form-data; name="MAX_FILE_SIZE"
100000
------WebKitFormBoundaryePkpFF7tjBAqx29L
Content-Disposition: form-data; name="uploadedfile"; filename="hello.o"
Content-Type: application/x-object
... contents of file goes here ...
------WebKitFormBoundaryePkpFF7tjBAqx29L--
and finally all you have to do is to implement a servlet that can handle the file upload request, then you do whatever that you want to do with the file, take a look at this file upload tutorial
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// Create path components to save the file
final String path = request.getParameter("destination");
final Part filePart = request.getPart("file");
final String fileName = getFileName(filePart);
OutputStream out = null;
InputStream filecontent = null;
final PrintWriter writer = response.getWriter();
try {
out = new FileOutputStream(new File(path + File.separator
+ fileName));
filecontent = filePart.getInputStream();
int read = 0;
final byte[] bytes = new byte[1024];
while ((read = filecontent.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
writer.println("New file " + fileName + " created at " + path);
LOGGER.log(Level.INFO, "File{0}being uploaded to {1}",
new Object[]{fileName, path});
} catch (FileNotFoundException fne) {
writer.println("You either did not specify a file to upload or are "
+ "trying to upload a file to a protected or nonexistent "
+ "location.");
writer.println("<br/> ERROR: " + fne.getMessage());
LOGGER.log(Level.SEVERE, "Problems during file upload. Error: {0}",
new Object[]{fne.getMessage()});
} finally {
if (out != null) {
out.close();
}
if (filecontent != null) {
filecontent.close();
}
if (writer != null) {
writer.close();
}
}
}
private String getFileName(final Part part) {
final String partHeader = part.getHeader("content-disposition");
LOGGER.log(Level.INFO, "Part Header = {0}", partHeader);
for (String content : part.getHeader("content-disposition").split(";")) {
if (content.trim().startsWith("filename")) {
return content.substring(
content.indexOf('=') + 1).trim().replace("\"", "");
}
}
return null;
}

Categories

Resources