I'm trying to make android download a zip file from my web server using a php page to download it.
If I download using a static link to the zip file, it works great, but i'm trying to download using a php file with this code:
function file_list($d,$x){
foreach(array_diff(scandir($d,1),array('.','..')) as $f)if(is_file($d.'/'.$f)&&(($x)?ereg($x.'$',$f):1))$l[]=$f;
return $l;
}
$arr = file_list("../download/",".zip");
$filename = $arr[0];
$filepath = "../download/".$arr[0];
if(!file_exists($filepath)){
die('Error: File not found.');
} else {
// Set headers
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
readfile($filepath);
}
If I access the php file in my browser, it downloads the zip just great!
Now, in the Android side, it downloads like it's supposed but the name of the zip is getZip.php (php file name) and the file size is 22.
This is the code that does the downloading stuff on the Android
int count;
try {
downloadCoords();
URL url = new URL(aurl[0]);
URLConnection conexion = url.openConnection();
conexion.connect();
int lengthOfFile = conexion.getContentLength();
Log.d("ANDRO_ASYNC", "Length of file: " + lengthOfFile);
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
if(!f.isDirectory()){
f.mkdirs();
}
Uri u = Uri.parse(url.toString());
File uf = new File(""+u);
zipname = uf.getName();
Log.d("ANDRO_ASYNC", "Zipname: " + zipname);
File zipSDCARD = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+zipname);
if(!zipSDCARD.isFile()){
Log.d("zipSDCARD.isFile()","false");
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream("/sdcard/" + zipname);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lengthOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}
successDownload = true;
} catch (Exception e) {
successDownload = false;
Log.e("Error","DownloadZip",e);
}
What needs to be done, is getting the zipname correctly and the ziplength too.
Thanks in advance.
Well, I solved it using php to write a link to the zip dynamically to the screen using this script:
function file_list($d,$x){
foreach(array_diff(scandir($d,1),array('.','..')) as $f)if(is_file($d.'/'.$f)&&(($x)?ereg($x.'$',$f):1))$l[]=$f;
return $l;
}
$arr = file_list("../download/",".zip");
$filename = $arr[0];
$filepath = "http://".$_SERVER['SERVER_NAME']."/download/".$arr[0];
print($filepath);
Then on the android, I used a BufferedReader to get the link correctly:
private String getZipURL(){
String result = "";
InputStream is = null;
try{
String url = ZipURL;
HttpPost httppost = new HttpPost(url);
HttpParams httpParameters = new BasicHttpParams();
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
int timeoutSocket = 3000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
DefaultHttpClient httpclient = new DefaultHttpClient(httpParameters);
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("getZipURL", "Error in http connection "+e.toString());
return null;
}
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
return result;
}catch(Exception e){
Log.e("convertZipURL", "Error converting result "+e.toString());
return null;
}
}
It may seem wrong, but it works as I want. I posted the code so I can get a workaround for someone with the same problem. Thanks!
Related
currently I can recognize speech to text using google's speech api. Now that I have this, I was just wondering if there is a way I can stream the response of transcribed text and give it more text to transcribe at the same time. In other words I want to speak into the microphone, and as I speak I want a response from the google servers. The code I am using currently:
System.out.println("openning connection");
HttpsURLConnection httpConn = null;
ByteBuffer buff = ByteBuffer.wrap(data);
byte[] destdata = new byte[2048];
int resCode = -1;
OutputStream out = null;
try {
URL url = new URL(urlStr);
URLConnection urlConn = url.openConnection();
if (!(urlConn instanceof HttpsURLConnection)) {
throw new IOException ("URL must be HTTPS");
}
httpConn = (HttpsURLConnection)urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("User-Agent", USER_AGENT);
httpConn.setDoOutput(true);
httpConn.setRequestProperty("AcceptEncoding", "gzip,deflate,sdch");
httpConn.setChunkedStreamingMode(0); //TransferType: chunked
httpConn.setRequestProperty("Content-Type", "audio/l16; rate=" + sampleRate);
// this opens a connection, then sends POST & headers.
out = httpConn.getOutputStream();
//beyond 15 sec duration just simply writing the file
// does not seem to work. So buffer it and delay to simulate
// bufferd microphone delivering stream of speech
// re: net.http.ChunkedOutputStream.java
while(buff.remaining() >= destdata.length){
buff.get(destdata);
out.write(destdata);
};
byte[] lastr = new byte[buff.remaining()];
buff.get(lastr, 0, lastr.length);
out.write(lastr);
out.close();
resCode = httpConn.getResponseCode();
if(resCode >= HttpURLConnection.HTTP_UNAUTHORIZED){//Stops here if Google doesn't like us/
System.out.println("unauthorized");
throw new HTTPException(HttpURLConnection.HTTP_UNAUTHORIZED);//Throws
}
String line;//Each line that is read back from Google.
BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
while ((line = br.readLine( )) != null) {
System.out.println(line);
if(line.length()>19 && resCode > 100 && resCode < HttpURLConnection.HTTP_UNAUTHORIZED){
GoogleResponse gr = new GoogleResponse();
parseResponse(line, gr);
fireResponseEvent(gr);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {httpConn.disconnect();}
Thanks for any help.
Getting the above error when trying to download large data using HttpGet
String uri = "";
getMethod = executeGet(uri);
httpClient.executeMethod(getMethod);
InputStream istream = getMethod.getResponseBodyAsStream();
byte[] data = IOUtils.toByteArray(istream);
FileUtils.writeByteArraytoFile(new File("xxx.zip"),data)
You are using a temporary byte array that might be the cause of the problem.
You can directly write the content of the stream to your file.
String uri = "";
getMethod = executeGet(uri);
httpClient.executeMethod(getMethod);
InputStream istream = getMethod.getResponseBodyAsStream();
IOUtils.copy(istream, new FileOutputStream(new File("xxx.zip"));
You're reading the entire response into the byte[] (memory). Instead, you could stream the output as you read it from istream with something like,
File f = new File("xxx.zip");
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(f));) {
int c = -1;
while ((c = istream.read()) != -1) {
os.write(c);
}
} catch (Exception e) {
e.printStackTrace();
}
I want to read the content of a webpage with the following methods, but I only get 60-70 percent of it.
I've tried 2 different methods to read the webpage, both with the same result. I also tried different Urls. I get no errors or timeouts.
What I am doing wrong ?
URL url = new URL(uri.toString());
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try
{
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null)
{
sb.append(line + "\n");
}
br.close();
this.content = sb.toString();
}
finally
{
urlConnection.disconnect();
}
AND
HttpGet get = new HttpGet(uri);
HttpClient defaultHttp = new DefaultHttpClient(httpParameters);
HttpResponse response = defaultHttp.execute(get);
StatusLine status = response.getStatusLine();
if(status.getStatusCode() == HttpStatus.SC_OK)
{
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
String encoding = "utf-8";
//long length = entity.getContentLength();
//if(entity.getContentEncoding() != null)
//{
// encoding = entity.getContentEncoding().getValue();
//}
//if(length > 0)
//{
byte[] buffer = new byte[1024];
long read = 0;
do
{
read = stream.read(buffer);
if(read > 0)
{
this.content += new String(buffer, encoding);
}
}while(read > 0);
//}
}
#edit
I've tried it with C# and WinForms. I read the complete html source of that webpage.
With java-android it doesn't work.
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.kicker.de");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string content = reader.ReadToEnd();
reader.Close();
response.Close();
the httpurlconnection in apache's util jar has limited the biggest bytes in a response, i couldn't remember the number of it.
But in most of time ,may you use the http conncetion in UI thread , so sometimes it's not safe,and maybe will be killed, you can choose to deal with the http request in a thread but not the UI thread. So I want to know if you do it in the UT thread
I have currently the same Problem. I tried my Code in a simple Java Application and I receive the whole content. But on Android, the Content is incomplete. This Question is now a year old. I guess you have solved it in the meantime. Can you please add your Solution?
Edit:
I wrote the content into a File on my Android Device. The Content was complete!
It seems logcat doesn´t show the complete Output you receive from the Devie.
(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.
The url: http://www.teamliquid.net/replay/download.php?replay=1830 is a download link to a .rep file.
My question is: how to download this content in java knowing the name of the original rep file in order to save it with a defined prefix, like path/_.rep
//I was trying to run wget from java but I don't see how to get the original file's name.
Get the redirected URL,
http://www.teamliquid.net/replay/upload/coco%20vs%20snssoflsekd.rep
You can get the filename from this URL.
It's tricky to get the redirected URL. See my answer to this question on how to do it with Apache HttpClient 4,
HttpClient 4 - how to capture last redirect URL
EDIT: Here is a sample using HttpClient 4.0,
String url = "http://www.teamliquid.net/replay/download.php?replay=1830";
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpContext context = new BasicHttpContext();
HttpResponse response = httpClient.execute(httpget, context);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
throw new IOException(response.getStatusLine().toString());
HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute(
ExecutionContext.HTTP_REQUEST);
String currentUrl = URLDecoder.decode(currentReq.getURI().toString(), "UTF-8");
int i = currentUrl.lastIndexOf('/');
String fileName = null;
if (i < 0) {
fileName = currentUrl;
} else {
fileName = currentUrl.substring(i+1);
}
OutputStream os = new FileOutputStream("/tmp/" + fileName);
InputStream is = response.getEntity().getContent();
byte[] buf = new byte[4096];
int read;
while ((read = is.read(buf)) != -1) {
os.write(buf, 0, read);
}
os.close();
After running this code, I get this file,
/tmp/coco vs snssoflsekd.rep