Java Image Downloader

Download Images with Java

Whenever your company gets new software, you’re bound to work overtime as a programmer. The staff figured out that you can load images into the POS software and the sales staff can see the image for each part. Hooray…for them.

“This shouldn’t be a problem for you, right Dino? We absolutely need this to work. This would improve sales drastically!” …Right.

So I contact the company and ask them if there’s any way to import the images in bulk. They tell me that there is. Apparently you can upload an entire folder into the system. As long as each image is named exactly like the part number, the system will link the image to that particular part. Seems like an inefficient use of resources, but ok. We only have 17,000 part numbers. We wholesale wheels and tires and there are a lot of items.

I have all of the images on the website. The way they’re named is brand/model_finish.jpg/png for wheels and brand/model.jpg/png for tires. Each wheel has a brand, a model, and a finish, so the XXR 575 Phantom Black would be stored as xxr/575_phantom_black.jpg for each part number matching those three criteria. A tire has no finish (just rubber), so a Delinte DS8 would be stored as delinte/ds8.jpg.

The database stores all of the parts. The brand, model, wheel finish, etc, are separated into different tables for normalization purposes. When a person goes to a particular page on the site, the data for that page is retrieved from the table(s), the image src is constructed, and the image is displayed next to each part number.

Great! I just need to go through my database, extract the data, construct the image src for each item and download the image. My programming language of choice? Java.

Since I need the MySQL connector, I decide to make this a maven project. In my pom.xml file, I include the mysql-connector-java dependency.

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.19</version>
    </dependency>
</dependencies>
Next it’s time to create the DBConnection class. This will just connect to the backed-up database on my local server.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

class DBConnection {

    private static final String USERNAME = "eci";
    private static final String PASSWORD = "eci123";
    private static final String CONN     = "jdbc:mysql://localhost:3306/eci";

    static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(CONN, USERNAME, PASSWORD);
    }
}
Inside the Main class, I specify whether I want to retrieve data for wheels or tires. The main method then calls either the getWheelQuery() or getTireQuery(). Each one of these methods just returns a String (SQL statement). The query is then executed and the data is stored in the resultSet.
import java.sql.*;

public class Main {

    private static String type = "wheels"; // or tires

    public static void main(String[] args) {

        String sql_query = ( type.equals("wheels") ) ? getWheelQuery() : getTireQuery() ;

        try (
                Connection connection = DBConnection.getConnection();
                Statement statement = connection.createStatement(
                        ResultSet.TYPE_SCROLL_INSENSITIVE,
                        ResultSet.CONCUR_READ_ONLY
                );
                ResultSet resultSet = statement.executeQuery( sql_query );
        ){

            Item.getItems( resultSet, type );

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static String getWheelQuery() {
        return "SELECT " +
                "wheels.id as id, " +
                "wheels.item_number as item_number, " +
                "brand.brand_name as brand, " +
                "model.model_name as model, " +
                "wheel_finish.finish as finish " +
                "FROM wheels " +
                "JOIN brand ON wheels.brand = brand.id " +
                "JOIN model ON wheels.model = model.id " +
                "JOIN wheel_finish ON wheels.full_finish = wheel_finish.id WHERE wheels.active = 1";
    }

    private static String getTireQuery() {
        return "SELECT " +
                "tires.id as id, " +
                "tires.item_number as item_number, " +
                "brand.brand_name as brand, " +
                "model.model_name as model " +
                "FROM tires " +
                "JOIN brand ON tires.brand = brand.id " +
                "JOIN model ON tires.model = model.id WHERE tires.active = 1";
    }
}
The resultSet and the type (wheel or tire) arguments are passed to the Item.getItems() method. The getItem() method calls either the downloadWheels() or downloadTires() method. For each item inside the database, the columns are sanitized to remove any characters that are not used in image creation, and the image is saved (hopefully). Since the website does allow for both jpg and png files, both are constructed and tested for.
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;

class Item {

    private static String[] match = {"/", "& ", "&", "-", ","};

    static void getItems(ResultSet resultSet, String type) throws SQLException {

        System.out.println("Displaying all items");

        if ( type.equals("wheels") ) {
            while( resultSet.next() )
                System.out.println( downloadWheels( resultSet ) );

        } else if ( type.equals("tires") ) {
            while( resultSet.next() )
                System.out.println( downloadTires( resultSet ) );
        }

        System.out.println("Finished");
    }

    private static String downloadWheels(ResultSet resultSet) throws SQLException {
        String item_number = resultSet.getString( "item_number");
        String brand       = resultSet.getString( "brand" );
        String model       = resultSet.getString( "model" );
        String finish      = resultSet.getString( "finish" );

        brand  = sanitizeData( brand );
        model  = sanitizeData( model );
        finish = sanitizeData( finish );

        String image_location = "http://website.com/version_2/img/wheels/" + brand + "/" + model + "_" + finish + ".jpg";

        try(InputStream in = new URL( image_location ).openStream()){
            Files.copy(in, Paths.get("D:/DB/FCWT/applications/eci-website-images/wheels/" + item_number + ".jpg"));
        } catch (IOException e) {
            //try with png
            try(InputStream in = new URL( image_location.replace( ".jpg", ".png" ) ).openStream()) {
                Files.copy(in, Paths.get("D:/DB/FCWT/applications/eci-website-images/wheels/" + item_number + ".jpg"));
            } catch ( IOException ignored ) {}
        }

        return image_location;
    }

    private static String downloadTires(ResultSet resultSet) throws SQLException {
        String item_number = resultSet.getString( "item_number");
        String brand       = resultSet.getString( "brand" );
        String model       = resultSet.getString( "model" );

        brand  = sanitizeData( brand );
        model  = sanitizeData( model );

        String image_location = "http://website.com/version_2/img/tires/" + brand + "/" + model + ".jpg";

        try(InputStream in = new URL( image_location ).openStream()){
            Files.copy(in, Paths.get("D:/DB/FCWT/applications/eci-website-images/tires/" + item_number + ".jpg"));
        } catch (IOException e) {
            //try with png
            try(InputStream in = new URL( image_location.replace( ".jpg", ".png" ) ).openStream()) {
                Files.copy(in, Paths.get("D:/DB/FCWT/applications/eci-website-images/tires/" + item_number + ".jpg"));
            } catch ( IOException ignored ) {}
        }

        return image_location;
    }

    private static String sanitizeData( String str ) {
        str = str.toLowerCase();

        for ( String replacement : match )
            str = str.replace( replacement, "" );

        str = str.replace(" ", "_");

        return str;
    }
}

After only a few minutes, the wheels and tires folders were filled with images whose names matched the part numbers they represented. I dragged the folder into the POS software and watched the magic happen. After only a couple of hours since they first approached me to do this, 17,000 images were loaded into the system and the entire company was happy. I’m going to ask the sales staff daily if they’re selling more since the images are now loaded…I mean it was of paramount importance after all.

https://github.com/dinocajic/java-web-image-downloader

Leave a Reply