My Java program downloads static map images from Google maps which shows the route line. If I go to this link in my browser, I get the correct image which is a map with directional polyline.
But when I download the image from the same URL with my Java program, I get this instead:
Both URLs look the same to me, I can't work out what's wrong. Here is my code if anyone can spot something out of place?
Code:
try {
String mapImgUrl = "https://maps.googleapis.com/maps/api/staticmap?size=300x300&path=enc:" + polyline + "&key=AIzaSyBn2qYJcHoNCgNQZv1mcycnUo06sJDZPBs";
String imageFileName = houseNumber + " " + address + ".jpg";
URL url = new URL(mapImgUrl);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(imageFileName);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
ImageIcon imgIcon = new ImageIcon((new ImageIcon(imageFileName))
.getImage().getScaledInstance(400, 400, java.awt.Image.SCALE_SMOOTH));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JLabel labelMap = new JLabel();
labelMap.setIcon(imgIcon);
panelMap.add(labelMap);
}
});
The polyline data is correct, I have compared the data I get from the JSON in my browser with the data I get from my program, and they match. This is the polyline data straight from the API if it helps anyway:
c{utHdfqJJaA`AoI\\oATo#Xe#P[R_#NYFYHs#AGAQDe#LYHGNCF?h#[Za#bBuDtA_Dp#gAR[J[#i#?SF]FIJEJAj#m#f#iAbByDlQoa#Pm#By#CS?YBSFOHKLCXOr#SbE}G~#gBfAiBdH_MjAwBFa#j#_ARYQg#kAkDIBIEEI?M#GMMQYgBiEaD{HJOH[`Hy`#d#iC{CgBgEcC}CeBb#gC
I think the issue is you haven't URL encoded the poly line.
Use: java.net.URLEncoder
String mapImgUrl = "https://maps.googleapis.com/maps/api/staticmap?size=300x300&path=enc:"
+ URLEncoder.encode(polyline, "utf-8") + "&key=<key>";
Note the encode(String) method which doesn't require the character encoding is deprecated. Also, make sure you import from the public package, java.net
I found the problem. The polyline portion of the URL was null due to the thread that gets the polyline data not finishing before the thread that sets up the URL started. I solved this by joining the threads.
Related
This is the qr-code generator, I put on String qrCodeData to try access the storage of my phone and open up a file, but it doesnt work. Turns out the generated qr code only gives the link.
public class QRCode {
public static void main(String[] args) {
try {
String qrCodeData = "Device storage/Download/japanese/Mastering_Kanji_1500.pdf";
String filePath = "D:\\QR code project\\Generated QR codes\\qr.png";
String charset = "UTF-8"; // or "ISO-8859-1"
Map < EncodeHintType, ErrorCorrectionLevel > hintMap = new HashMap < EncodeHintType, ErrorCorrectionLevel > ();
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
BitMatrix matrix = new MultiFormatWriter().encode(
new String(qrCodeData.getBytes(charset), charset),
BarcodeFormat.QR_CODE, 200, 200, hintMap);
MatrixToImageWriter.writeToFile(matrix, filePath.substring(filePath
.lastIndexOf('.') + 1), new File(filePath));
System.out.println("QR Code image created successfully! and stored at location"+filePath);
} catch (Exception e) {
System.err.println(e);
}
}
}
We are able to view and manipulate PDF files via the PDFBox library.
Android version.
We may also use MuPDF. It has an Android version.
Interpret the received link as a file or download it to storage, then proceed to interface with PDFBox library.
Note that file downloading and access on Android should now be done via Room interface or SQLite as recommended by Google.
Hope this helps.
I'm trying to build a jsoup based java app to automatically download English subtitles for films (I'm lazy, I know. It was inspired from a similar python based app). It's supposed to ask you the name of the film and then download an English subtitle for it from subscene.
I can make it reach the download link but I get an Unhandled content type error when I try to 'go' to that link. Here's my code
public static void main(String[] args) {
try {
String videoName = JOptionPane.showInputDialog("Title: ");
subscene(videoName);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void subscene(String videoName){
try {
String siteName = "http://www.subscene.com";
String[] splits = videoName.split("\\s+");
String codeName = "";
String text = "";
if(splits.length>1){
for(int i=0;i<splits.length;i++){
codeName = codeName+splits[i]+"-";
}
videoName = codeName.substring(0, videoName.length());
}
System.out.println("videoName is "+videoName);
// String url = "http://www.subscene.com/subtitles/"+videoName+"/english";
String url = "http://www.subscene.com/subtitles/title?q="+videoName+"&l=";
System.out.println("url is "+url);
Document doc = Jsoup.connect(url).get();
Element exact = doc.select("h2.exact").first();
Element yuel = exact.nextElementSibling();
Elements lis = yuel.children();
System.out.println(lis.first().children().text());
String hRef = lis.select("div.title > a").attr("href");
hRef = siteName+hRef+"/english";
System.out.println("hRef is "+hRef);
doc = Jsoup.connect(hRef).get();
Element nonHI = doc.select("td.a40").first();
Element papa = nonHI.parent();
Element link = papa.select("a").first();
text = link.text();
System.out.println("Subtitle is "+text);
hRef = link.attr("href");
hRef = siteName+hRef;
Document subDownloadPage = Jsoup.connect(hRef).get();
hRef = siteName+subDownloadPage.select("a#downloadButton").attr("href");
Jsoup.connect(hRef).get(); //<-- Here's where the problem lies
}
catch (java.io.IOException e) {
System.out.println(e.getMessage());
}
}
Can someone please help me so I don't have to manually download subs?
I just found out that using
java.awt.Desktop.getDesktop().browse(java.net.URI.create(hRef));
instead of
Jsoup.connect(hRef).get();
downloads the file after prompting me to save it. But I don't want to be prompted because this way I won't be able to read the name of the downloaded zip file (I want to unzip it after saving using java).
Assuming that your files are small, you can do it like this. Note that you can tell Jsoup to ignore the content type.
// get the file content
Connection connection = Jsoup.connect(path);
connection.timeout(5000);
Connection.Response resultImageResponse = connection.ignoreContentType(true).execute();
// save to file
FileOutputStream out = new FileOutputStream(localFile);
out.write(resultImageResponse.bodyAsBytes());
out.close();
I would recommend to verify the content before saving.
Because some servers will just return a HTML page when the file cannot be found, i.e. a broken hyperlink.
...
String body = resultImageResponse.body();
if (body == null || body.toLowerCase().contains("<body>"))
{
throw new IllegalStateException("invalid file content");
}
...
Here:
Document subDownloadPage = Jsoup.connect(hRef).get();
hRef = siteName+subDownloadPage.select("a#downloadButton").attr("href");
//specifically here
Jsoup.connect(hRef).get();
Looks like jsoup expects that the result of Jsoup.connect(hRef) should be an HTML or some text that it's able to parse, that's why the message states:
Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml
I followed the execution of your code manually and the last URL you're trying to access returns a content type of application/x-zip-compressed, thus the cause of the exception.
In order to download this file, you should use a different approach. You could use the old but still useful URLConnection, URL or use a third party library like Apache HttpComponents to fire a GET request and retrieve the result as an InputStream, wrap it into a proper writer and write your file into your disk.
Here's an example about doing this using URL:
URL url = new URL(hRef);
InputStream in = url.openStream();
OutputStream out = new BufferedOutputStream(new FileOutputStream("D:\\foo.zip"));
final int BUFFER_SIZE = 1024 * 4;
byte[] buffer = new byte[BUFFER_SIZE];
BufferedInputStream bis = new BufferedInputStream(in);
int length;
while ( (length = bis.read(buffer)) > 0 ) {
out.write(buffer, 0, length);
}
out.close();
in.close();
Here's my problem. I have a txt file called "sites.txt" . In these i type random internet sites. My Goal is to save the first image of each site. I tried to filter the Server response by the img tag and it actually works for some sites, but for some not.
The sites where it works the img src starts with http:// ... the sites it doesnt work start with anything else.
I also tried to add the http:// to the img src images which didnt have it, but i still get the same error:
Exception in thread "main" java.net.MalformedURLException: no protocol:
at java.net.URL.<init>(Unknown Source)
My current code is:
public static void main(String[] args) throws IOException{
try {
File file = new File ("sites.txt");
Scanner scanner = new Scanner (file);
String url;
int counter = 0;
while(scanner.hasNext())
{
url=scanner.nextLine();
URL page = new URL(url);
URLConnection yc = page.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine = in.readLine();
while (!inputLine.toLowerCase().contains("img"))inputLine = in.readLine();
in.close();
String[] parts = inputLine.split(" ");
int i=0;
while(!parts[i].contains("src"))i++;
String destinationFile = "image"+(counter++)+".jpg";
saveImage(parts[i].substring(5,parts[i].length()-1), destinationFile);
String tmp=scanner.nextLine();
System.out.println(url);
}
scanner.close();
}
catch (FileNotFoundException e)
{
System.out.println ("File not found!");
System.exit (0);
}
}
public static void saveImage(String imageUrl, String destinationFile) throws IOException {
// TODO Auto-generated method stub
URL url = new URL(imageUrl);
String fileName = url.getFile();
String destName = fileName.substring(fileName.lastIndexOf("/"));
System.out.println(destName);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destinationFile);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
}
I also got a tip to use the apache jakarte http client libraries but i got absolutely no idea how i could use those i would appreciate any help.
A URL (a type of URI) requires a scheme in order to be valid. In this case, http.
When you type www.google.com into your browser, the browser is inferring you mean http:// and automatically prepends it for you. Java doesn't do this, hence your exception.
Make sure you always have http://. You can easily fix this using regex:
String fixedUrl = stringUrl.replaceAll("^((?!http://).{7})", "http://$1");
or
if(!stringUrl.startsWith("http://"))
stringUrl = "http://" + stringUrl;
An alternative solution
Simply try with ImageIO that contains static convenience methods for locating ImageReaders and ImageWriters, and performing simple encoding and decoding.
Sample code:
// read a image from the URL
// I used the URL that is your profile pic on StackOverflow
BufferedImage image = ImageIO
.read(new URL(
"https://www.gravatar.com/avatar/3935223a285ab35a1b21f31248f1e721?s=32&d=identicon&r=PG&f=1"));
// save the image
ImageIO.write(image, "jpg", new File("resources/avatar.jpg"));
When you're scraping the site's HTML for image elements and their src attributes, you'll run into several different representations of URLs.
Some examples are:
resource = https://google.com/images/srpr/logo9w.png
resource = google.com/images/srpr/logo9w.png
resource = //google.com/images/srpr/logo9w.png
resource = /images/srpr/logo9w.png
resource = images/srpr/logo9w.png
For the second through fifth ones, you'll need to build the rest of the URL.
The second one may be more difficult to differentiate from the fourth and fifth ones, but I'm sure there are workarounds. The URL Standard leads me to believe you won't see it as often, because I don't think it's technically valid.
The third case is pretty simple. If the resource variable starts with //, then you just need to prepend the protocol/scheme to it. You can do this with the site object you have:
url = site.getProtocol() + ":" + resource
For the fourth and fifth cases, you'll need to prepend the resource with the entire site's URL.
Here's a sample application that uses jsoup to parse the HTML, and a simple utility method to build the resource URL. You're interested in the buildResourceUrl method. Also, it doesn't handle the second case; I'll leave that to you.
import java.io.*;
import java.net.*;
import org.jsoup.*;
import org.jsoup.nodes.*;
import org.jsoup.select.*;
public class SiteScraper {
public static void main(String[] args) throws IOException {
URL site = new URL("https://google.com/");
Document doc = Jsoup.connect(site.toString()).get();
Elements images = doc.select("img");
for (Element image : images) {
String src = image.attr("src");
System.out.println(buildResourceUrl(site, src));
}
}
static URL buildResourceUrl(URL site, String resource)
throws MalformedURLException {
if (!resource.matches("^(http|https|ftp)://.*$")) {
if (resource.startsWith("//")) {
return new URL(site.getProtocol() + ":" + resource);
} else {
return new URL(site.getProtocol() + "://" + site.getHost() + "/"
+ resource.replaceAll("^/", ""));
}
}
return new URL(resource);
}
}
This obviously won't cover everything, but it's a start. You may run into problems when the URL you're trying to access is in a subdirectory of the root of the site (i.e., http://some.place/under/the/rainbow.html). You may even encounter base64 encoded data URI's in the src attribute... It really depends on the individual case and how far you're willing to go.
I have been trying to find a way to write metadata to a PNG and I have tried quite alot.
I can read the data using the pngj library using:
PngReader pngr = new PngReader(file);
pngr.readSkippingAllRows(); // reads only metadata
for (PngChunk c : pngr.getChunksList().getChunks()) {
if (!ChunkHelper.isText(c)) continue;
PngChunkTextVar ct = (PngChunkTextVar) c;
String key = ct.getKey();
String val = ct.getVal();
System.out.print(key + " " + val + "\n" );
}
pngr.close();
And it works great. But I need to write to it.
I have tried:
public boolean writeCustomData(String key, String value) throws Exception {
PngReader pngr = new PngReader(currentImage);
PngWriter png = new PngWriter(new FileOutputStream(currentImage), pngr.imgInfo);
png.getMetadata().setText(key, value);
return true;
}
But this does nothing.
And I have tried using the answer from Writing image metadata in Java, preferably PNG
this works (kinda) but my read function cant see it.
If you want to add a chunk to the image, you must read and write the full image. Example
PngReader pngr = new PngReader(origFile);
PngWriter pngw = new PngWriter(destFile, pngr.imgInfo, true);
// instruct the writer to copy all ancillary chunks from source
pngw.copyChunksFrom(pngr.getChunksList(), ChunkCopyBehaviour.COPY_ALL);
// add a new textual chunk (can also be done after writing the rows)
pngw.getMetadata().setText("my key", "my val");
// copy all rows
for (int row = 0; row < pngr.imgInfo.rows; row++) {
IImageLine l1 = pngr.readRow();
pngw.writeRow(l1);
}
pngr.end();
pngw.end();
If you need more performance, you can read/write the chunks at a lower level, see this example.
Try this:
Stream pngStream = new System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
PngBitmapDecoder pngDecoder = new PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapFrame pngFrame = pngDecoder.Frames[0];
InPlaceBitmapMetadataWriter pngInplace = pngFrame.CreateInPlaceBitmapMetadataWriter();
if (pngInplace.TrySave() == true)
{
pngInplace.SetQuery("/Text/Description", "Have a nice day.");
}
pngStream.Close();
I have this code where I am trying to read an image from Url:
public class question_insert {
public static String latex(String tex) throws IOException {
String urltext = "http://chart.apis.google.com/chart?cht=tx&chl="+tex;
URL url = new URL(urltext);
BufferedReader in = new BufferedReader(new InputStreamReader(url
.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
// Process each line.
System.out.println(inputLine.toString());
}
in.close();
return inputLine;}
But what I am getting is unreadable code. The url gives only one image try this:
http://chart.apis.google.com/chart?cht=tx&chl=2+2%20\frac{3}{4}
What should I do to embed the image into Html?
First of all it is not clear what you mean by image in Html format ? You could Base64 encode its binary data, but is that what you really want?
How do you expect to output a PNG picture returned by your URL to a text console (that is System.out)?
Second, the way you're retrieving the image is not functional even if you were to store it on a disk as a PNG file, because Reader and its derivatives like BufferedReader are used to read character data. From Reader API:
Abstract class for reading character streams
You need to read binary (byte) data, so you need to stick with BufferedInputStream
After some thinking I realized that embedding image into HTML is what you really want:
public static void main(String[] args) throws Exception {
String urltext = "http://chart.apis.google.com/chart?cht=tx&chl=2+2%20\\frac{3}{4}";
URL url = new URL(urltext);
BufferedInputStream bis = new BufferedInputStream(url.openStream());
byte[] imageBytes = new byte[0];
for(byte[] ba = new byte[bis.available()];
bis.read(ba) != -1;) {
byte[] baTmp = new byte[imageBytes.length + ba.length];
System.arraycopy(imageBytes, 0, baTmp, 0, imageBytes.length);
System.arraycopy(ba, 0, baTmp, imageBytes.length, ba.length);
imageBytes = baTmp;
}
System.out.println("<img src='data:image/png;base64," + DatatypeConverter.printBase64Binary(imageBytes) + "'>");
}
The result is:
<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAhCAIAAACnV0fJAAAABmJLR0QA/wD/AP+gvaeTAAAC/klEQVRIiaWWv0vzQBjHr2ltsGDEyf+giAg5iIO4iiJC8cciQhaLk9IOGpcOii5ugj/qZoeWgqtFXJxrBSnUQTAianTJEJBcjeRCwr3D+caY1ijpd7rnc8lzz/PkuYdECCEgrDDGlmXF43GWZV0YC+0un8/f3993dXU9PT0JgpDL5T43SChdXV0JgnB5eUkIqVarPM+XSiW6xYQLkGEYlmVfXl4AAENDQwCAer3eUYyEENM06aJSqUAIq9UqNcN7JIQYhlGr1RYWFg4ODlwYMmuqer3++vra3d0ty7JlWZ1m7UrX9eHh4XQ67Y8RY9xsNh3H8QXSll9fX5fLZbrmOK6vr+/m5sYwDOD24+HhoaqqmqYpijI1NZXJZIL5xsaGqqqpVIrjOJpoJBL5ynpvb+/8/JzGTD/c/v5+ACeEZLPZ7e1tur67u+N5PpfLUTNimmYqlZqZmVleXqZnTExM2LZdqVTm5uZa+cXFRTQatSxra2vLMAyGYWRZhhBubm7G43EAANB1HUIIIdR1nR6STqd5nn9+fm7LXZMQYpomQshtTKoYx3Hr6+u0wDQWTdMSiUR/f39b7h0KLMt6zfbd8/j4KAhCNpv9I29VhHyfZouLi6qqnp6efhalHW82m/64/iuRSHybZsViESF0dHTkc+flCKGxsbGfPEqS9JX12dnZ0tISxtiXRStHP8u2beCWKZPJuK/t7Oy8v78H8AABQoiiKJIkaZpGz3l7exNFMYD/8mVs2xZFUZZlbzmSyWS5XG7LT05OWsuHMXbbKAYAmJ2d9T2RTCYDuE/FYrHRaOzu7n7av2YRLEVRRkdHvX3a0cQFABQKBd+16chjPp8fGRmJxb41dXiPDw8PCKHJyUkfD+nRcZzj4+O1tbXWrZAeS6XS9PS077JS+SfFX2QYxvz8/MDAADVrtVpvb+/g4KAoihDCkN3jvcvj4+MrKyv0UhNCQv5J9fT0eM1oNOqSjrqn0Wisrq7qun57eytJEsYYhKujK8dxPj4+XJOG+Q+Ygl+7nqaLKQAAAABJRU5ErkJggg=='>
Isn't that great? Anything for you!
Well, I don't know if that is what you want because it seems that nobody does. But if you want to get this output
<img style="-webkit-user-select: none"
src="http://chart.apis.google.com/chart?cht=tx&chl=2+2%20\frac{3}{4}" />
you will have to use this code
public static String latex(String tex) {
String url = "http://chart.apis.google.com/chart?cht=tx&chl=" + tex;
return "<img style=\"-webkit-user-select: none\" src=\"" + url + "\"/>";
}
Also you might have to escape some characters like \ in the tex parameter.
To get your image, you should try to use ImageIO API like this
try {
URL url = new URL(urltext);
BufferedImage img = ImageIO.read(url);
} catch (IOException e) {
e.printStackTrace();
}
http://chart.apis.google.com/chart?cht=tx&chl=2+2%20\frac{3}{4}
Note that this URL is wrong. This shows 22 3/4 instead of the intended 2 + 2 3/4.The request parameter containing special characters needs to be URL-encoded as follows.
http://chart.apis.google.com/chart?cht=tx&chl=2%2B2%20%5Cfrac%7B3%7D%7B4%7D
You can achieve this with URLEncoder#encode().
String chl = "2+2 \\frac{3}{4}";
String url = "http://chart.apis.google.com/chart?cht=tx&chl=" + URLEncoder.encode(chl, "UTF-8");
Back to your functional requirement:
What should I do to embed the image into Html?
If your sole functional requirement is to display the image as available behind the mentioned URL by an HTML <img> element in a HTML/JSP page, then you need to use JSTL <c:url> tag to URL-encode request parameters containing special characters.
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<c:url var="url" value="http://chart.apis.google.com/chart">
<c:param name="cht" value="tx" />
<c:param name="chl" value="2+2 \\frac{3}{4}" />
</c:url>
Then you can just refer it as ${url} (as declared in var attribute of <c:url>) in the src attribute of the HTML <img> element:
<img src="${url}" />
Reading a binary image stream from an URL as a character stream and storing in a string as you initially attempted makes completely no utter sense. You also wouldn't open image files in notepad, for example.