Java - HttpServer not serving images - java

I have a simple setup including a HttpServer with some context to load image and CSS files:
public class Server {
private HttpServer httpServer;
public Server(int port, String path, HttpHandler handler) {
try {
httpServer = HttpServer.create(new InetSocketAddress(port), 0);
httpServer.createContext(path, handler);
// load css files
List<String> cssFiles = new ArrayList<String>();
Files.walk(Paths.get("../css")).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
cssFiles.add(filePath.getFileName().toString());
}
});
for (String cssFile : cssFiles) {
httpServer.createContext("/css/" + cssFile, new CssHandler(cssFile));
}
// load image files
List<String> imgFiles = new ArrayList<String>();
Files.walk(Paths.get("../images")).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
imgFiles.add(filePath.getFileName().toString());
}
});
for (String imgFile : imgFiles) {
httpServer.createContext("/images/" + imgFile, new ImageHandler(imgFile));
}
httpServer.setExecutor(null);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
this.httpServer.start();
}
}
In addition to that there is a css handler which works perfectly fine and and an image handler class, which serves images defined in html tags, BUT images which are included via css tag "background-image" cannot be loaded.. why?
ImageHandler:
class ImageHandler implements HttpHandler {
private String img;
public ImageHandler(String img) {
this.img = img;
}
#Override
public void handle(HttpExchange http) throws IOException {
if (http.getRequestMethod().equals("GET")) {
System.out.println("img transfered..." + img);
try {
StringBuilder contentBuilder = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new FileReader("../images/" + img));
String str;
while ((str = in.readLine()) != null) {
contentBuilder.append(str);
}
in.close();
} catch (IOException e) {
}
String response = contentBuilder.toString();
http.sendResponseHeaders(200, response.length());
OutputStream os = http.getResponseBody();
os.write(response.getBytes());
os.flush();
os.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
Sooo,
this works:
<img src="images/example.png"/>
But this one doesn't work:
background-image: url("images/example.png");
Could anybody explain why and suggest how to solve this problem?

Since partial URLs are relative to the source of the style sheet, and your paths structure looks like this:
/images/example.png
/css/example.css
So image URLs in example.css should either be absolute (/images/example.png), or have the correct relative path (../images/example.png).

Related

How to download a file into the specific folder in java?

I am working on an application which will download 3rd party dependencies to a particular folder and then execute dependency check on it. The files downloaded can be of any type, they can be zip, jar or may b a folder. I am trying to find a code example but nothing seems to work for me. I tried NIO in java but that seems to work only for writing to a particular file not folder. Below is code where I used NIO
// Checking If The File Exists At The Specified Location Or Not
Path filePathObj = Paths.get(filePath);
boolean fileExists = Files.exists(filePathObj);
if(fileExists) {
try {
urlObj = new URL(sampleUrl);
rbcObj = Channels.newChannel(urlObj.openStream());
fOutStream = new FileOutputStream(filePath);
fOutStream.getChannel().transferFrom(rbcObj, 0, Long.MAX_VALUE);
System.out.println("! File Successfully Downloaded From The Url !");
} catch (IOException ioExObj) {
System.out.println("Problem Occured While Downloading The File= " + ioExObj.getMessage());
} finally {
try {
if(fOutStream != null){
fOutStream.close();
}
if(rbcObj != null) {
rbcObj.close();
}
} catch (IOException ioExObj) {
System.out.println("Problem Occured While Closing The Object= " + ioExObj.getMessage());
}
}
} else {
System.out.println("File Not Present! Please Check!");
}```
public Class CopyAndWrite {
public static final String SOURCES = "C:\\Users\\Administrator\\Desktop\\resources";
public static final String TARGET = "C:\\Users\\Administrator\\Desktop\\111";
public static void main (String[]args) throws IOException {
Path startingDir = Paths.get(SOURCES);
Files.walkFileTree(startingDir, new FindJavaVisitor());
}
private static class FindJavaVisitor extends SimpleFileVisitor<Path> {
#Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
if (!StringUtils.equals(dir.toString(), SOURCES)) {
Path targetPath = Paths.get(TARGET + dir.toString().substring(SOURCES.length()));
if (!Files.exists(targetPath)) {
Files.createDirectory(targetPath);
}
}
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path targetPath = Paths.get(TARGET + file.toString().substring(SOURCES.length()));
copyFile(targetPath, Files.readAllBytes(file));
return FileVisitResult.CONTINUE;
}
}
private static void copyFile (Path path,byte[] bytes){
// write file
try {
Files.write(path, bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Using OKHttpClient to download the file and place in a folder.
Request request = new Request.Builder().url(downloadUrl).build();
Response response;
try {
response = client.newCall(request).execute();
if (response.isSuccessful()) {
fileName = abc.zip
Path targetPath = new File(inDir + File.separator + fileName).toPath();
try (FileOutputStream fos = new FileOutputStream(targetPath)) {
fos.write(response.body().bytes());
}
return 0;
}
} catch (IOException e) {
logger.error(e.getMessage());
}```

Downloading Multiple Files Parallelly or Asynchronously in Java

Here I am trying to download multiple files one after another:
Environment - Java 1.6
public List<Attachment> download(List<Attachment> attachments)
{
for(Attachment attachment : attachments) {
attachment.setDownStatus("Failed");
String destLocation = "C:\Users\attachments";
try {
String attUrl = attachment.getUrl();
String fileName = attachment.getFileName();
URL url = new URL(attUrl);
File fileLocation = new File(destLoc, fileName);
FileUtils.copyURLToFile(url, fileLocation);
if(fileLocation.exists()) {
attachment.setDownStatus("Completed");
}
} catch(Exception e) {
attachment.setDownStatus("Failed");
} finally {
attachment.setDestLocation(destLocation);
}
}
return attachments;
}
I am downloading the file from provided URL (http://cdn.octafinance.com/wp-content/uploads/2015/07/google-hummingbird.jpg).
FileUtils.copyURLToFile(url, fileLocation);
The above code does its downloading job perfectly, without any issues.
My Problem:
If the list of attachments are more it will take more time, so I would like to make it an asynchronous or parallel process instead of downloading sequentially.
Use Java 8 Streams in combination with ForkJoinPool
public List<Attachment> download(List<Attachment> attachments) throws InterruptedException, ExecutionException {
ForkJoinPool forkJoinPool = new ForkJoinPool(attachments.size());
return forkJoinPool.submit(() -> processAttachments(attachments)).get();
}
private List<Attachment> processAttachments(List<Attachment> attachments) {
return attachments.stream().parallel().map(attachment -> processSingleAttachment(attachment)).collect(Collectors.toList());
}
private Attachment processSingleAttachment(Attachment attachment){
//business logic to download single attachment
.
.
}
public List<Attachment> download(List<Attachment> attachments)
{
ExecutorService executorService = Executors.newCachedThreadPool();
for(final Attachment attachment : attachments){
executorService.submit(new Runnable() {
#Override
public void run() {
try{
String attUrl = attachment.getUrl();
String fileName = attachment.getFileName();
String destLocation = "C:\Users\attachments";
URL url = new URL(attUrl);
String fileLocation = new File(destLoc, fileName);
FileUtils.copyURLToFile(url, fileLocation);
if(fileLocation.exists()) {
attachment.setDownStatus("Completed");
}
}
catch(Exception e){
attachment.setDownStatus("Failed");
}
}
});
}
executorService.shutdown();
return attachments;
}
Actually, after carefully looking, Boris' code is faulty and will indeed not set some stuff sometimes. Here's a better version that fixes that:
public List<Attachment> download(List<Attachment> attachments) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<Attachment>> futures = new ArrayList<Future<Attachment>>();
for (final Attachment attachment : attachments) {
futures.add(executorService.submit(new Callable<Attachment>() {
#Override
public Attachment call() throws Exception {
return doDownload(attachment);
}
}));
}
for (Future<Attachment> future: futures) {
try {
future.get();
} catch (Exception ex) {
// Do something
}
}
return attachments;
}
private Attachment doDownload(Attachment attachment) throws Exception {
attachment.setDownStatus("Failed");
attachment.setDestLocation("C:\\Users\\attachments");
String attUrl = attachment.getUrl();
String fileName = attachment.getFileName();
URL url = new URL(attUrl);
File fileLocation = new File(attachment.getDestLocation(), fileName);
FileUtils.copyURLToFile(url, fileLocation);
if (fileLocation.exists()) {
attachment.setDownStatus("Completed");
}
return attachment;
}
However, this is absolutely not optimal given your structure of Attachment and how you use it. I did not fix that: I only answered the question as it was asked.

Can't write text into .properties file with FileOutputStream on android

This is a part of the code I have in my SettingsActivity.java file:
public class SettingsActivity extends Activity {
Thread refresh = new Thread() {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Config.writeFile();
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
if (new File(MainActivity.ConfigPath).exists()) {
Config.loadFile();
} else {
Config.writeFile();
}
refresh.start();
}
}
And this is in my Config.java file:
public class Config {
public static void writeFile() {
try {
Properties properties = new Properties();
properties.setProperty("StartOnBoot", String.valueOf(MainActivity.StartOnBoot));
//StartOnBoot is a boolean in the MainActivity.java file
File file = new File("config/app.properties");
file.setWritable(true);
FileOutputStream fileOut = new FileOutputStream(file);
properties.store(fileOut, "Favorite Things");
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void loadFile() {
try {
Properties properties = new Properties();
FileInputStream fileIn = new FileInputStream(new File("config/app.properties"));
properties.load(fileIn);
MainActivity.StartOnBoot = Boolean.valueOf(properties.getProperty("StartOnBoot"));
fileIn.close();
System.out.println(properties.getProperty("StartOnBoot"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
This is what my Project explorer window looks like
This is what is shown in a logfile from logcat:
07-09 16:16:32.416: W/System.err(621): at
java.io.FileOutputStream.(FileOutputStream.java:94)
And the .properties file still remains empty.
Any ideas how to make it work?
PS:
-API 10
-Target SDK Version 22
-I didn't add any permissions to the AndroidManifest.xml file
For handling properties in Android, use this class:
public class MyPropertiesHolder {
public static int MODE_CREATE = 0;
public static int MODE_UPDATE = 1;
private Context context;
private String filename;
private Properties properties;
public MyPropertiesHolder(Context context, String filename, int mode) throws IOException {
this.context = context;
this.filename = filename;
this.properties = new Properties();
if(mode != MODE_CREATE) {
FileInputStream inputStream = context.openFileInput(filename);
properties.load(inputStream);
inputStream.close();
}
}
public String getProperty(String key){
return (String) properties.get(key);
}
public void setProperty(String key, String value) {
properties.setProperty(key, value);
}
public void commit() throws IOException {
FileOutputStream outputStream = context.openFileOutput(filename, Context.MODE_PRIVATE);
properties.store(outputStream, "");
outputStream.close();
}
}
This is how you use the above class (assuming you are in an Activity):
Creating a new properties file:
MyPropertiesHolder propHolder = new MyPropertiesHolder(this, "test.properties", MyPropertiesHolder.MODE_CREATE);
propHolder.setProperty("test1", "test1");
propHolder.setProperty("test2", "test2");
propHolder.commit();
Updating existing properties file:
MyPropertiesHolder propHolder2 = new MyPropertiesHolder(this, "test.properties", MyPropertiesHolder.MODE_UPDATE);
String test1 = propHolder2.getProperty("test1");
String test2 = propHolder2.getProperty("test2");
propHolder2.setProperty("test3", "test3");
propHolder2.setProperty("test4", "test4");
propHolder2.commit();
Note: You won't see this file in assets directory.

Wicket: redirecting to wicket page using setResponsePage

I have a wicket page which has a link ADD PRODUCT. On clicking the link a modal window open which takes the product information.
ProductAddPanel.java
public class ProductAddPanel extends Panel {
private InlineFrame uploadIFrame = null;
private ModalWindow window;
private Merchant merchant;
private Page redirectPage;
private List<Component> refreshables;
public ProductAddPanel(String id,final Merchant mct,ModalWindow window,List<Component> refreshables,Page p) {
super(id);
this.window = window;
merchant = mct;
redirectPage = p;
this.refreshables = refreshables;
setOutputMarkupId(true);
}
#Override
protected void onBeforeRender() {
super.onBeforeRender();
if (uploadIFrame == null) {
// the iframe should be attached to a page to be able to get its pagemap,
// that's why i'm adding it in onBeforRender
addUploadIFrame();
}
}
// Create the iframe containing the upload widget
private void addUploadIFrame() {
IPageLink iFrameLink = new IPageLink() {
#Override
public Page getPage() {
return new UploadIFrame(window,merchant,redirectPage,refreshables) {
#Override
protected String getOnUploadedCallback() {
return "onUpload_" + ProductAddPanel.this.getMarkupId();
}
};
}
#Override
public Class<UploadIFrame> getPageIdentity() {
return UploadIFrame.class;
}
};
uploadIFrame = new InlineFrame("upload", iFrameLink);
add(uploadIFrame);
}
}
ProductAddPanel.html
<wicket:panel>
<iframe wicket:id="upload" frameborder="0"style="height: 600px; width: 475px;overflow: hidden"></iframe>
</wicket:panel>
I am using a Iframe to upload the image. I have added a iframe to my ProductPanel.html. Because it is not possible to upload file using ajax submit.
UploadIframe.java
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
DynamicImage imageEntry = new DynamicImage();
if(uploadField.getFileUpload() != null && uploadField.getFileUpload().getClientFileName() != null){
FileUpload upload = uploadField.getFileUpload();
String ct = upload.getContentType();
if (!imgctypes.containsKey(ct)) {
hasError = true;
}
if(upload.getSize() > maximagesize){
hasError = true;
}
if(hasError == false){
System.out.println("######################## Image can be uploaded ################");
imageEntry.setContentType(upload.getContentType());
imageEntry.setImageName(upload.getClientFileName());
imageEntry.setImageSize(upload.getSize());
if(imageEntry != null){
try {
save(imageEntry,upload.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}else{
target.appendJavaScript("$().toastmessage('showNoticeToast','Please select a valid image!!')");
System.out.println("#################### Error in image uploading ###################");
}
}else{
System.out.println("########################### Image not Selected #####################");
}
MerchantProduct mp =new MerchantProduct();
Product p = new Product();
Date d=new Date();
try {
p.setProductImage(imageEntry.getImageName());
mp.setProduct(p);
Ebean.save(mp);
} catch (Exception e) {
e.printStackTrace();
}
for(Component r: refreshables){
target.add(r);
}
window.close(target);
setResponsePage(MerchantProductPage.class);
}
public void save(DynamicImage imageEntry, InputStream imageStream) throws IOException{
//Read the image data
ByteArrayOutputStream baos = new ByteArrayOutputStream();
copy(imageStream,baos);
baos.close();
byte [] imageData = baos.toByteArray();
baos = null;
//Get the image suffix
String suffix = null;
if("image/gif".equalsIgnoreCase(imageEntry.getContentType())){
suffix = ".gif";
}else if ("image/jpeg".equalsIgnoreCase(imageEntry.getContentType())) {
suffix = ".jpeg";
} else if ("image/png".equalsIgnoreCase(imageEntry.getContentType())) {
suffix = ".png";
}
// Create a unique name for the file in the image directory and
// write the image data into it.
File newFile = createImageFile(suffix);
OutputStream outStream = new FileOutputStream(newFile);
outStream.write(imageData);
outStream.close();
imageEntry.setImageName(newFile.getAbsolutePath());
}
//copy data from src to dst
private void copy(InputStream source, OutputStream destination) throws IOException{
try {
// Transfer bytes from source to destination
byte[] buf = new byte[1024];
int len;
while ((len = source.read(buf)) > 0) {
destination.write(buf, 0, len);
}
source.close();
destination.close();
if (logger.isDebugEnabled()) {
logger.debug("Copying image...");
}
} catch (IOException ioe) {
logger.error(ioe);
throw ioe;
}
}
private File createImageFile(String suffix){
UUID uuid = UUID.randomUUID();
File file = new File(imageDir,uuid.toString() + suffix);
if(logger.isDebugEnabled()){
logger.debug("File "+ file.getAbsolutePath() + "created.");
}
return file;
}
}
}
I am using setResonsePage() to redirect to initial page on which "Add Product" link is present. So that i get the refreshed page having new product information.
My problem is that modal window is not closing on window.close() and inside that window i am getting the refreshed page.
My requirement is that Modal window should close and page should be refreshed. I am passing the Parentpage.class in my setResponsePage().
Any help and advices appreciated! Thanks in advance.
In the ParentPage.class on which modal window is open i called setWindowClosedCallback() method in which I am adding getPage() to target so that page will refresh when modal window is closed.
Here is the code for same
modalDialog.setWindowClosedCallback(new ModalWindow.WindowClosedCallback()
{
private static final long serialVersionUID = 1L;
#Override
public void onClose(AjaxRequestTarget target)
{
target.addComponent(getPage());
}
});

Using JSoup to save the contents of this url: http://www.aw20.co.uk/images/logo.png to a file

I am try to use JSoup to get the contents of this url http://www.aw20.co.uk/images/logo.png, which is the image logo.png, and save it to a file. So far I have used JSoup to connect to http://www.aw20.co.uk and get a Document. I then went and found the absolute url for the image I am looking for, but now am not sure how to this to get the actual image. So I was hoping someone could point me in the right direction to do so? Also is there anyway I could use Jsoup.connect("http://www.aw20.co.uk/images/logo.png").get(); to get the image?
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class JGet2 {
public static void main(String[] args) {
try {
Document doc = Jsoup.connect("http://www.aw20.co.uk").get();
Elements img = doc.getElementsByTag("img");
for (Element element : img) {
String src = element.absUrl("src");
System.out.println("Image Found!");
System.out.println("src attribute is: " + src);
if (src.contains("logo.png") == true) {
System.out.println("Success");
}
getImages(src);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
private static void getImages(String src) throws IOException {
int indexName = src.lastIndexOf("/");
if (indexName == src.length()) {
src = src.substring(1, indexName);
}
indexName = src.lastIndexOf("/");
String name = src.substring(indexName, src.length());
System.out.println(name);
}
}
You can use Jsoup to fetch any URL and get the data as bytes, if you don't want to parse it as HTML. E.g.:
byte[] bytes = Jsoup.connect(imgUrl).ignoreContentType(true).execute().bodyAsBytes();
ignoreContentType(true) is set because otherwise Jsoup will throw an exception that the content is not HTML parseable -- that's OK in this case because we're using bodyAsBytes() to get the response body, rather than parsing.
Check the Jsoup Connection API for more details.
Jsoup isn't designed for downloading the content of the url.
Since you are able to use a third party library, you can try apache common IO for downloading the content of a given URL to file using:
FileUtils.copyURLToFile(URL source, File destination);
It is only one line.
This method does not work well. Please careful when using it.
byte[] bytes = Jsoup.connect(imgUrl).ignoreContentType(true).execute().bodyAsBytes();
You can use these methods or part of these methods to solve your problem.
NOTE: IMAGE_HOME is the absolute path. e.g. /home/yourname/foldername
public static String storeImageIntoFS(String imageUrl, String fileName, String relativePath) {
String imagePath = null;
try {
byte[] bytes = Jsoup.connect(imageUrl).ignoreContentType(true).execute().bodyAsBytes();
ByteBuffer buffer = ByteBuffer.wrap(bytes);
String rootTargetDirectory = IMAGE_HOME + "/"+relativePath;
imagePath = rootTargetDirectory + "/"+fileName;
saveByteBufferImage(buffer, rootTargetDirectory, fileName);
} catch (IOException e) {
e.printStackTrace();
}
return imagePath;
}
public static void saveByteBufferImage(ByteBuffer imageDataBytes, String rootTargetDirectory, String savedFileName) {
String uploadInputFile = rootTargetDirectory + "/"+savedFileName;
File rootTargetDir = new File(rootTargetDirectory);
if (!rootTargetDir.exists()) {
boolean created = rootTargetDir.mkdirs();
if (!created) {
System.out.println("Error while creating directory for location- "+rootTargetDirectory);
}
}
String[] fileNameParts = savedFileName.split("\\.");
String format = fileNameParts[fileNameParts.length-1];
File file = new File(uploadInputFile);
BufferedImage bufferedImage;
InputStream in = new ByteArrayInputStream(imageDataBytes.array());
try {
bufferedImage = ImageIO.read(in);
ImageIO.write(bufferedImage, format, file);
} catch (IOException e) {
e.printStackTrace();
}
}
Also is there anyway I could use Jsoup.connect("http://www.aw20.co.uk/images/logo.png").get(); to get the image?
No, JSoup will only get text and such but cannot be used to download files or binary data. That being said, just use the file name and path that you've gotten through JSoup and then use standard Java I/O to download the file.
I've used NIO to do the downloading. i.e.,
String imgPath = // ... url path to image
String imgFilePath = // ... file path String
URL imgUrl;
ReadableByteChannel rbc = null;
FileOutputStream fos = null;
try {
imgUrl = new URL(imgPath);
rbc = Channels.newChannel(imgUrl.openStream());
fos = new FileOutputStream(imgFilePath);
// setState(EXTRACTING + imgFilePath);
fos.getChannel().transferFrom(rbc, 0, 1 << 24);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (rbc != null) {
try {
rbc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Categories

Resources