I would like to implement a function where you send a URL of a photo and my server will automatically download and store it in a specified folder.
I studied some use cases, but as a beginner in this area of the web, I was a bit lost. I thought about FTP but is not exactly what I want.
Like that, function on my webservice (using Java + Tomcat + AXIS2)
void getPhoto(URL url){
//receive a photo and store at folder /photos
}
but, I don't know what use, I was looking for some httppost or httpget, should I still looking for in this way? Has a dummie sample, to show me the basic way?
I would like to implement a function where you send a URL of a photo and my server will automatically download and store it in a specified folder.
That's not exactly "uploading", but just "downloading".
Just call openStream() on the URL and you've an InputStream which you can do anything with. Writing to a FileOutputStream for example.
InputStream input = url.openStream();
// ...
hey use this code to download.
try {
URL url = new URL(url of file );
URLConnection conection = url.openConnection();
conection.connect();
InputStream input = new BufferedInputStream(url.openStream());
String downloadloc = "D:\"; // or anything
OutputStream output = new FileOutputStream(downloadloc
+ "\name of file.ext");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
}
You want to look at using an HttpURLConnection, call it's 'connect' and 'getInputStream' methods, continually reading from that stream and writing that data to a file with e.g. a FileOutputStream.
To download a file using a URL, as an alternative to what suggested by others, you can take a look to Apache Commons HttpClient.
There is also a well written tutorial.
Related
I'm writing a program that builds stuff in a GUI (blah blah blah... irrelevant details), and the user is allowed to export that data as a .tex file which can be compiled to a PDF. Since I don't really want to assume they have a TeX environment installed, I'm using an API (latexonline.cc). That way, I can construct an HTTP GET request, send it to the API, then (hopefully!) return the PDF in a byte-stream. The issue, though, is that when I submit the request, I'm only getting the page data back from the request instead of the data from the PDF. I'm not sure if it's because of how I'm doing my request or not...
Here's the code:
... // preceding code
DataOutputStream dos = new DataOutputStream(new FileOutputStream("test.pdf"));
StringBuilder httpTex = new StringBuilder();
httpTex.append(this.getTexCode(...)); // This appends the TeX code (nothing wrong here)
// Build the URL and HTTP request.
String texURL = "https://latexonline.cc/compile?text=";
String paramURL = URLEncoder.encode(httpTex.toString(), "UTF-8");
URL url = new URL(texURL + paramURL);
byte[] buffer = new byte[1024];
try {
InputStream is = url.openStream();
int bufferLen = -1;
while ((bufferLen = is.read(buffer)) > -1) {
this.getOutputStream().write(buffer, 0, bufferLen);
}
dos.close();
is.close();
} catch (IOException ex) {
ex.printStackTrace();
}
Edit: Here's the data I'm getting from the GET request:
https://pastebin.com/qYtGXUsd
Solved! I used a different API and it works perfectly.
https://github.com/YtoTech/latex-on-http
I have an android app that downloads and uses a file at runtime. The file is valid as I can download it via the browser and open it up, etc. However my app kept reporting that the file is corrupted.
After investigation I discovered the server (which I have no control over) is returning an incorrect "Content-Length:" (~180 vs ~120000). The header is the culprit as I confirmed the issue by downloading the file with curl - which also resulted in a truncated file.
After some research I concluded that my use of BufferedInputStream to append to a ByteArrayBuffer is autosizing the byte array to the url connections content length. To circumvent this, I tried to use ByteArrayOutputStream instead, however this solved nothing.
Anybody know of a way to download a file if the Content-Length is incorrectly set? A browser can.
Here's my latest attempt:
public static void downloadFileFromRemoteUrl(String urlString, String destination){
try {
URL url = new URL(urlString);
File file = new File(destination);
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
byte[] buffer = new byte[1024];
int curLength = 0;
int newLength = 0;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while((newLength = inputStream.read(buffer))>0)
{
curLength += newLength;
byteArrayOutputStream.write(buffer, 0, newLength);
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(byteArrayOutputStream.toByteArray());
fos.close();
android.util.Log.d("DB UPDATE", "Done downloading database. Size: " + byteArrayOutputStream.toByteArray().length);
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
After some research I concluded that my use of BufferedInputStream to append to a ByteArrayBuffer is autosizing the byte array to the url connections content length.
Nonsense. You are crediting those classes with paranormal powers. How could an output stream possibly become aware of the Content-length header? The URLConnection's input stream is being terminated at the content-length. Correctly.
To circumvent this, I tried to use ByteArrayOutputStream instead, however this solved nothing.
Of course not.
Anybody know of a way to download a file if the Content-Length is incorrectly set?
You could use a Socket and engage in HTTP yourself, which is less trivial than it sounds. But the problem is at the server and that's where it should be fixed. Complain. Or else #Zong Yu is correct and the page is HTML containing JavaScript, say.
NB You don't need to read the entire file into memory:
while((newLength = inputStream.read(buffer))>0)
{
curLength += newLength;
fos.write(buffer, 0, newLength);
}
My final "solution" was to realize I was dealing with a 301 redirect response and not the actual resource! I updated the section that handles my url, checking for a 301 and if exists, update the url. The new url contained the Content-Length that corresponded with the file I was downloading.
// start by creating an http url connection object
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
// determine if this is a redirect
boolean redirect = false;
int status = httpURLConnection.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) {
if (status == HttpURLConnection.HTTP_MOVED_TEMP
|| status == HttpURLConnection.HTTP_MOVED_PERM
|| status == HttpURLConnection.HTTP_SEE_OTHER)
redirect = true;
}
// if it is, we need a new url
if (redirect) {
String newUrl = httpURLConnection.getHeaderField("Location");
httpURLConnection = (HttpURLConnection) new URL(newUrl).openConnection();
}
Try Fetch. Fetch is an in app download manager for Android. It's very easy to use. Find the GitHub page here. The project comes with several demos that you can try out. Disclaimer: I'm the creator of Fetch, and it is open source.
I am using the following code from an android application to upload a blob to Azure Blob Storage. Note: the sasUrl parameter below is a signed url acquired from my web service :
// upload file to azure blob storage
private static Boolean upload(String sasUrl, String filePath, String mimeType) {
try {
// Get the file data
File file = new File(filePath);
if (!file.exists()) {
return false;
}
String absoluteFilePath = file.getAbsolutePath();
FileInputStream fis = new FileInputStream(absoluteFilePath);
int bytesRead = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while ((bytesRead = fis.read(b)) != -1) {
bos.write(b, 0, bytesRead);
}
fis.close();
byte[] bytes = bos.toByteArray();
// Post our image data (byte array) to the server
URL url = new URL(sasUrl.replace("\"", ""));
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setConnectTimeout(15000);
urlConnection.setReadTimeout(15000);
urlConnection.setRequestMethod("PUT");
urlConnection.addRequestProperty("Content-Type", mimeType);
urlConnection.setRequestProperty("Content-Length", "" + bytes.length);
urlConnection.setRequestProperty("x-ms-blob-type", "BlockBlob");
// Write file data to server
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
wr.write(bytes);
wr.flush();
wr.close();
int response = urlConnection.getResponseCode();
if (response == 201 && urlConnection.getResponseMessage().equals("Created")) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
The code is working fine for small blobs but when a blob reaches a certain size depending on the phone I am testing with, I start to get out of memory exceptions. I would like to split the blobs and upload them in blocks. However, all the examples I find on the web are C# based and are using the Storage Client library. I am looking for a Java/Android example that uploads a blob in blocks using the Azure Storage Rest API.
There is an Azure Storage Android library published here. A basic blob storage example is in the samples folder. The method you’d probably like to use is uploadFromFile in the blob class. This will, by default attempt to put the blob in a single put if the size is less than 64MB and otherwise send the blob in 4MB blocks. If you’d like to reduce the 64MB limit, you can set the singleBlobPutThresholdInBytes property on the BlobRequestOptions object of either the CloudBlobClient (which will affect all requests) or passed to the uploadFromFile method (to affect only that request). The storage library includes many convenient features such as automated retries and maximum execution timeout across the block put requests which are all configurable.
If you’d still like to use a more manual approach, the PutBlock and Put Block List API references are here and provide generic, cross-language documentation. These have nice wrappers in the CloudBlockBlob class of the Azure Storage Android library called uploadBlock and commitBlockList which may save you a lot of time in manual request construction and can provide some of the aforementioned conveniences.
I am trying to download a file from a given URL. The URL is not a direct file URL. When this URL is provided in browser manually, we get a prompt for download/save.
For example, http://www.my-domain.com/download/type/salary/format/excel
I have no issues in the URL which has the file name directly in the URL. In the above URL, based on the format and type, server generates the file.
In Java I am trying to download the file using the below code. The file is created, but the content is just the domain content and not the actual excel data.
URL url = new URL("http://www.my-domain.com/download/type/salary/format/excel");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
float totalDataRead = 0;
BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
FileOutputStream fos = new FileOutputStream("c:\\test.xls");
BufferedOutputStream bout = new BufferedOutputStream(fos, 1024);
byte[] data = new byte[1024];
int i = 0;
while ((i = in.read(data, 0, 1024)) >= 0) {
totalDataRead = totalDataRead + i;
bout.write(data, 0, i);
}
bout.close();
in.close();
The content is whatever the server sent for that URL. You can't do anything about that from the client end. If it contained Javascript for example it won't get executed.
When you want to solve a problem you have to use the adequate tools to get the thing done. The adequate tools can be found at poi.apache.org. Have a look at Apache POI.
I am writing a custom proxy as a web service client for our main application, which uses REST web services. For security reasons, I am trying to use a servlet on the client side as a proxy to retrieve a PDF from the server side and then display that in the application web browser through the client app.
As the heart of this, I have this piece of code:
protected void copy(HttpResponse fromResponse, HttpServletResponse toResponse)
throws IOException{
HttpEntity entity = fromResponse.getEntity();
for(Header header:fromResponse.getAllHeaders()){
toResponse.setHeader(header.getName(), header.getValue());
}
BufferedInputStream inputStream = new BufferedInputStream(entity.getContent());
BufferedOutputStream outputStream = new BufferedOutputStream(toResponse.getOutputStream());
int oneByte;
int byteCount = 0;
while((oneByte = inputStream.read()) >= 0){
outputStream.write(oneByte);
++byteCount;
}
log.debug("Bytes copied:" + byteCount);
which should copy the PDF from the returned output stream to the current output stream and then return it.
When I run it, though, I get an error from Adobe Reader saying the file is damaged and could not be repaired. When I run the URL directly the file is fine, so it has to be something in the handoff. The byteCount is equal to the PDF file size.
Does anyone have an idea what the problem is?
By doing
while((inputStream.read(buffer)) >= 0){
outputStream.write(buffer);
}
you will always write the full length of buffer, regardless of its effective content length as write can only look at the buffer's size to determine what to write.
int count;
while(((count = inputStream.read(buffer))) >= 0){
outputStream.write(buffer,0,count);
}
should take care of that problem.
I closed outputStream after writing to it and it works fine.
I didn't think you were supposed to do that?