This should be an easy learning task but something went wrong:
Use API request to get image from some link and check it is in Base64 standard.
private static void getRequest() throws IOException {
URL url = new URL("http://apimeme.com/meme?meme=Alarm-Clock&top=Top+text&bottom=Bottom+text");
InputStream is = (InputStream) url.openStream();
FileInputStream imageInFile = new FileInputStream(is.toString());
byte imageData[] = new byte[2048];
imageInFile.read(imageData);
System.out.println(isBase64(imageInFile.toString()));
}
static boolean isBase64(String path) {
try {
Base64.getDecoder().decode(path);
return true;
} catch(IllegalArgumentException e) {
return false;
}
}
Right now problem is on line
InputStream is = (InputStream) url.openStream();
Server sends 403. How to fix this? Method isBase64 should work but the program doesn't reach this line.
Your need 3 header for avoid http 403 error code
private static void getRequest() throws IOException {
URL url = new URL("http://apimeme.com/meme?meme=Alarm-Clock&top=Top+text&bottom=Bottom+text");
URLConnection is = url.openConnection();
is.setRequestProperty("Host", "apimeme.com");
is.setRequestProperty("Cookie", "*");
is.setRequestProperty("User-Agent", "*");
byte[] imageData = new byte[2048];
File downloadFile = new File("download.png");
FileOutputStream outputStream = new FileOutputStream(downloadFile);
int read;
while ((read = is.getInputStream().read(imageData)) != -1) {
outputStream.write(imageData, 0, read);
}
outputStream.close();
System.out.println(isBase64(downloadFile.getAbsolutePath()));
}
403 is means that you do not have permission to view this URL. You cannot do anything to fix this client side, even authorization would not help (if the ressource required authorization, the server would send 401 instead). So to fix the issue, whoever is in charge of the web server delivering the URL you're trying to access will have to fix this - if they think you should have access.
Related
Someone is providing a S3 Presigned URL so that I can upload my images to that link. All my images are on the website. Is there a way in JAVA to copy the image URL to the new URL provided ?
I am trying to do this. Seems like an overkill
try {
// Get Image from URL
URL urlGet = new URL("http://something.com/something.png");
BufferedImage image = ImageIO.read(urlGet);
//for png
ImageIO.write(image, "png",new File("/something.png"));
// for jpg
//ImageIO.write(image, "jpg",new File("/something.jpg"));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "png", outputStream);
outputStream.flush();
byte[] imageInBytes = outputStream.toByteArray();
outputStream.close();
URL url = new URL(putUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod(HttpMethod.PUT);
connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, PNG_MIME_TYPE);
OutputStream stream = connection.getOutputStream();
try {
stream.write(imageInBytes);
} finally {
stream.close();
connection.disconnect();
}
switch (connection.getResponseCode()) {
case HttpURLConnection.HTTP_OK:
return "";
default:
break;
}
} catch (Exception e) {
log.error("Exception occured", e);
throw e;
}
There would be no point converting to BufferedImage and back for the copy when you can preserve the byte stream of the original files. The first part can be replaced with simple call to extract the bytes off your website:
byte[] imageInBytes = read(urlGet);
Where read() is:
private static byte[] read(URL url) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(16*1024);
try (var in = url.openStream()) {
in.transferTo(out);
}
return out.toByteArray();
}
If you use JDK11 onwards you could try the HttpClient class for the GET and POSTs, for example this does same as above if passing it urlGet.toURI():
private static byte[] read(URI uri) throws IOException, InterruptedException
{
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(uri).build();
var resp = client.send(request, BodyHandlers.ofByteArray());
return resp.body();
}
I'm trying to download a zip file through a java program using GitHub API.
The program I'm using is the following:
public static void main(String[] args) {
// create client
HttpClient client = HttpClient.newHttpClient();
// create request
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.github.com/repos/:owner/:repo/zipball/:ref")).build();
// use the client to send the asynchronous request
InputStream is = client.sendAsync(request, BodyHandlers.ofInputStream())
.thenApply(HttpResponse::body).join();
try {
FileOutputStream out = new FileOutputStream("outputZipFile.zip");
copy(is,out,1024);
out.close();
}catch(Exception e) {}
}
private static void copy(InputStream is, FileOutputStream out, int i) {
// TODO Auto-generated method stub
byte[] buf = new byte[i];
try {
int n = is.read(buf);
while(n>=0) {
out.write(buf,0,n);
n=is.read(buf);
}
out.flush();
}catch(IOException ioe) {
System.out.println(ioe.getStackTrace());
}
}
When I try to run this I get empty body so the output file will be empty as well.
I noticed that using HttpURLConnection insted of Java11 HttpClient makes it work but I'd prefer to use this Java11 feature in order to send asynchronous requests.
I can't understand what I'm doing wrong.
EDIT: The HttpURLConnection code I'm using at the moment is the following:
private void downloadVersion(String sha, String outputDestination) {
try {
URL url = new URL( getDownloadQuery(sha) );
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
if(authToken!=null)
connection.setRequestProperty("Authorization", "Bearer " + authToken) ;
connection.setRequestMethod("GET");
InputStream in = connection.getInputStream();
FileOutputStream out = new FileOutputStream(outputDestination);
copy(in, out, 1024);
out.close();
} catch (Exception e) {}
}
Your url (when set to correct github repos) may be returning redirect status 302. To make HTTP client follow redirects replace HttpClient client = HttpClient.newHttpClient() with use of HttpClient.newBuilder(). You can also simplify your code with try with resources and making use of InputStream.transferTo:
HttpClient client = HttpClient.newBuilder().followRedirects(Redirect.ALWAYS).build();
URI uri = URI.create("https://api.github.com/repos/:owner/:repo/zipball/:ref");
HttpRequest request = HttpRequest.newBuilder().uri(uri).build();
// use the client to send the asynchronous request
InputStream is = client.sendAsync(request, BodyHandlers.ofInputStream())
.thenApply(HttpResponse::body).join();
try (FileOutputStream out = new FileOutputStream("outputZipFile.zip")) {
is.transferTo(out);
}
I'm using Java Web Start to grab and start an application and for this I must download data via a so-called jnlp protocol. Since this protocol is unknown for Java by default, I had to write my own URL stream handler.
My problem is that I don't know how to implement the getInputStream method,
// the custom URL stream handler
URL.setURLStreamHandlerFactory((String protocol)
-> "jnlp".equals(protocol) ? new URLStreamHandler() {
#Override
protected URLConnection openConnection(URL url) throws IOException {
return new URLConnection(url) {
#Override
public void connect() throws IOException {
System.out.println("connected");
}
#Override
public InputStream getInputStream() throws IOException {
/* -------------------- */
/* What to put in here? */
/* -------------------- */
}
};
}
} : null);
// Constructing the parametrized URL for Java Web Start...
URL url = new URL("jnlp", "localhost", 8080,
"application-connector/app?"
+ params.entrySet().stream().map(Object::toString)
.collect(joining("&")));
// Downloading and starting the application...
final File jnlp = File.createTempFile("temp", ".jnlp");
byte[] buffer = new byte[8192];
int len;
while ((len = url.openStream().read(buffer)) != -1) {
new FileOutputStream(jnlp).write(buffer, 0, len);
}
Desktop.getDesktop().open(jnlp);
which is necessary so I don't get the following error:
protocol doesn't support input
Typically a JNLP can just be downloaded from an http:/https: URL. E.g. :
URL url = new URL(
"https://docs.oracle.com/javase/tutorialJWS/samples/uiswing/WallpaperProject/Wallpaper.jnlp");
// Downloading and starting the application...
final File jnlp = File.createTempFile("temp", ".jnlp");
try (InputStream is = url.openStream();
FileOutputStream fos = new FileOutputStream(jnlp)) {
byte[] buffer = new byte[8192];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
}
System.out.println("JNLP file written to " + jnlp.getAbsolutePath());
//Desktop.getDesktop().open(jnlp);
new ProcessBuilder("cmd", "/c", "javaws", jnlp.getAbsolutePath())
.start();
Not sure of the environment this is for. Under Windows I found Desktop.open() wasn't launching, hence the direct call to javaws.
If the direct call to javaws is an option though, there is a much easier way, as it can launch a JNLP file directly from a URL:
new ProcessBuilder("cmd", "/c", "javaws",
"https://docs.oracle.com/javase/tutorialJWS/samples/uiswing/WallpaperProject/Wallpaper.jnlp")
.start();
I'm trying to download an imagen in java,using a function,
here is my code to send the function
saveImage(newString, folder.toString());
then, this is my function saveImage
public static void saveImage(String imageUrl,String folderpath) throws IOException {
URL url = new URL(imageUrl);
//String destName = folder;
//System.out.println(destName);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(folderpath);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
}
i tried from links here at stackoverflow, but anything works, all the time i got a
java.io.IOException: Server returned HTTP response code: 403 for URL
how can i fix it? the Exception, thank you
A 403 Forbidden HTTP status return code from a web server indicates that the server can be reached but refuses to take any action due to the web server being configured to deny access, for whatever reason, to the requested resource.
So there's nothing wrong with the code that you showed us, it's to do with the configuration of the web server that you're trying to get the image from.
Try using an Authenticator in order to set the authenticator default that will be used for all requests. You will need a user name and password.
It can be used something like this:
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"user", "password".toCharArray());
}
});
here is the code to fix it, if anyone want to use it.
public static void saveImage(String imageUrl, File folder, String m) throws IOException {
if (!folder.exists()) {
folder.mkdirs();
System.out.println("si quedo con el if folderpath----" + folder);
}
URL url = new URL(imageUrl);
//String destName = folder;
//System.out.println(destName);
m = m + ".jpg";
//final URL url = new URL(urlStr);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.0)");
final BufferedImage image = ImageIO.read(connection.getInputStream());
ImageIO.write(image, "jpg", new File(m));
}
I am using the following code to download a file within the WEB-INF
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String b = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("thecookie")) {
b = cookie.getValue();
}
}
}
BufferedReader br = new BufferedReader(new FileReader(b+"/logs.txt"));
String path = br.readLine();
br.close();
File file = new File(path+"/Results.xlsx");
FileInputStream fileIn = new FileInputStream(file);
ServletOutputStream out = response.getOutputStream();
response.setHeader("Content-Disposition", "attachment; filename=Result.xlsx");
response.setContentType(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
byte[] outputByte = new byte[4096];
int bytesRead;
//copy binary contect to output stream
while((bytesRead = fileIn.read(outputByte)) != -1)
{
out.write(outputByte, 0, bytesRead);
}
fileIn.close();
out.flush();
out.close();
}
along with this I want to download another file at the same location Results.csv I've tried using the same code above twice but it didn't work.
How to download multiple files without using zipoutputstream?
MIME/multipart responses are, as far as I know, not part of the HTTP standard. Some browsers seem to support it, but I recommend against using it.
Instead, you could pack those files into a ZIP file (using a ZipOutputStream), and return that as your response. That's also the way DropBox handles the download of multiple files at once.
It is possible but having them in separate requests if you plan to work within every browser.
Here a sample script for downloading a file via javascript
function downloadFile(url, name) {
var link = document.createElement("a");
link.download = name;
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
downloadFile(url1,filenam1);
downloadFile(url2,filenam2);
downloadFile(url3,filenam3);
...