com.look.UploadPostServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.look.UploadPostServlet.java

Source

package com.look;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

/*
 * Copyright 2015 Kevin Holland.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * UploadPostServlet handles the uploading of posts to both the Look server and database.
 * The uploaded image is stored in the build directory /images and a reference
 * to the image is stored in the database. The image name is changed to the
 * postID and the associated extension of the image. 
 * 
 * @author  Kevin Holland (GitHub: kholland950)
 * @date    04/25/2015
 * @updated 05/17/2015
 */
@WebServlet("/uploadServlet")
public class UploadPostServlet extends HttpServlet {
    //logger for debugging requests
    static final Logger log = Logger.getLogger(UploadPostServlet.class.getName());

    //directory for storing images 
    private String IMAGE_DIRECTORY = null;

    //constants for DB field names
    private static final String TITLE_FIELD_NAME = "title";
    private static final String DESCRIPTION_FIELD_NAME = "description";
    private static final String TAGS_FIELD_NAME = "tags";

    //variables for storing data about the post
    private String user = null;
    private String title = null;
    private String description = null;
    private String tags = null;
    private List<String> tagList;
    private String imageURL = null;
    //image extensions from uploaded image
    private String imageExtension = null;
    //image content
    private InputStream fileContent;

    //responseMessage from server.
    private String responseMessage = "";

    //-----------------------------------------------------------------------------------------------

    /**
     * Handles post request for uploading images and creating a post (image post)
     * @param request HttpRequest from client
     * @param response HttpResponse to be sent to client
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //must reset responseMessage on next post. Fixes unwanted error message bug
        responseMessage = "";

        //get real image directory path
        IMAGE_DIRECTORY = getServletContext().getRealPath("/images/");

        //get user attribute from session
        user = request.getSession().getAttribute("user").toString();

        //try to handle request
        boolean success = handleRequest(request);
        //if handling was not successful (bad input) forward to upload.jsp with message
        if (success == false) {
            request.setAttribute("title", title);
            request.setAttribute("description", description);
            request.setAttribute("tags", tags);
            request.setAttribute("message", responseMessage);
            getServletContext().getRequestDispatcher("/upload.jsp").forward(request, response);
            return;
        }

        Connection conn = null; // connection to the database

        int post_id = -1;

        try {
            // connects to the database
            conn = LookDatabaseUtils.getNewConnection();

            // constructs SQL statement
            String postSQL = "INSERT INTO posts (title, description, users_user_ID, image_url, time_posted)"
                    + " values (?, ?, ?, ?, CURRENT_TIMESTAMP)";
            PreparedStatement post_statement = conn.prepareStatement(postSQL);
            post_statement.setString(1, title);
            post_statement.setString(2, description);

            String userQuery = "SELECT user_id FROM users WHERE username=\"" + user + "\"";
            Statement userStatement = conn.createStatement();
            ResultSet userIDRS = userStatement.executeQuery(userQuery);
            userIDRS.next();
            int userID = userIDRS.getInt(1);
            post_statement.setInt(3, userID);

            post_statement.setString(4, imageURL);
            post_statement.executeUpdate();

            Statement postIDStatement = conn.createStatement();
            ResultSet postIDRS = postIDStatement
                    .executeQuery("SELECT post_id FROM posts WHERE image_url=\"" + imageURL + "\";");
            postIDRS.next();
            post_id = postIDRS.getInt(1);
            imageURL = FilenameUtils.getName(post_id + "." + imageExtension);
            String imagePermaSQL = "UPDATE posts " + "SET image_url= ? " + "WHERE post_id=" + post_id + ";";
            PreparedStatement imagePermaURL = conn.prepareStatement(imagePermaSQL);
            imagePermaURL.setString(1, imageURL);
            imagePermaURL.executeUpdate();

            if (!uploadFile()) {
                request.setAttribute("message", "Failed to upload");
                Statement removeStatement = conn.createStatement();
                removeStatement.executeUpdate("DELETE FROM posts WHERE post_id=" + post_id + ";");
                getServletContext().getRequestDispatcher("/upload.jsp").forward(request, response);
                return;
            }

            //if there are tags
            if (tagList != null && tagList.size() > 0) {
                //add tags to database
                String addTagSQL = "INSERT IGNORE INTO tags (tag) " + "VALUES (?); ";
                String addRelationshipSQL = "INSERT INTO tags_has_posts(tags_tag_id, posts_post_id) "
                        + "VALUES (?, ?);";
                for (String tag : tagList) {
                    PreparedStatement s = conn.prepareStatement(addTagSQL);
                    s.setString(1, tag);
                    s.executeUpdate();
                    ResultSet r = conn.createStatement()
                            .executeQuery("SELECT tag_id FROM tags WHERE tag='" + tag + "';");
                    r.next();
                    int tag_id = r.getInt(1);
                    PreparedStatement rS = conn.prepareStatement(addRelationshipSQL);
                    rS.setInt(1, tag_id);
                    rS.setInt(2, post_id);
                    rS.executeUpdate();
                }
            }

        } catch (SQLException ex) {
            responseMessage = "ERROR: " + ex.getMessage();
            log.warning(ex.getMessage());
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(UploadPostServlet.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (conn != null) {
                // closes the database connection
                try {
                    conn.close();
                } catch (SQLException ex) {
                    log.warning(ex.getMessage());
                }
            }

            response.sendRedirect("post?id=" + post_id);
            //getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
        }
    }

    /***************************************************************************
     * Saves user uploaded file to server
     * @return True if successfully stored on server, false otherwise
     */
    private boolean uploadFile() {
        File f = new File(IMAGE_DIRECTORY + File.separator + imageURL);
        OutputStream out;
        try {
            out = new FileOutputStream(f);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(UploadPostServlet.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        try {
            IOUtils.copy(fileContent, out);
            fileContent.close();
            out.close();
        } catch (IOException ex) {
            Logger.getLogger(UploadPostServlet.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        return true;
    }

    //-----------------------------------------------------------------------------------------------

    /***************************************************************************
     * Processes request data and saves into instance variables
     * @param request HttpServletRequest from client
     * @return True if successfully handled, false otherwise
     */
    private boolean handleRequest(HttpServletRequest request) {
        if (ServletFileUpload.isMultipartContent(request)) {
            try {
                List<FileItem> multiparts = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);

                boolean success = true;
                for (FileItem item : multiparts) {
                    if (!item.isFormField()) {
                        // Process form file field (input type="file").
                        String fieldName = item.getFieldName();
                        String filename = item.getName();
                        if (filename.equals("")) {
                            //only update responseMessage if there isn't one yet
                            if (responseMessage.equals("")) {
                                responseMessage = "Please choose an image";
                            }
                            success = false;
                        }
                        String clientFileName = FilenameUtils.getName("TEMP_" + item.getName().replaceAll(" ", ""));

                        imageExtension = FilenameUtils.getExtension(clientFileName);
                        imageURL = clientFileName + "." + imageExtension;
                        fileContent = item.getInputStream();
                    } else {
                        String fieldName = item.getFieldName();
                        String value = item.getString();
                        //only title is required
                        if (value.equals("") && (fieldName.equals("title"))) {
                            responseMessage = "Please enter a title";
                            success = false;
                        }
                        switch (fieldName) {
                        case TITLE_FIELD_NAME:
                            title = value;
                            break;
                        case DESCRIPTION_FIELD_NAME:
                            description = value;
                            break;
                        case TAGS_FIELD_NAME:
                            tags = value;
                            if (!tags.equals("")) {
                                tagList = new LinkedList<>(Arrays.asList(tags.split(" ")));
                                for (int i = 0; i < tagList.size(); i++) {
                                    String tag = tagList.get(i);
                                    if (tag.charAt(0) != '#') {
                                        if (responseMessage.equals("")) {
                                            responseMessage = "Tags must begin with #";
                                            success = false;
                                        }
                                        tagList.remove(i);
                                    } else if (!StringUtils.isAlphanumeric(tag.substring(1))) {
                                        log.info(tag.substring(1));
                                        if (responseMessage.equals("")) {
                                            responseMessage = "Tags must only contain numbers and letters";
                                            success = false;
                                        }
                                        tagList.remove(i);
                                    } else if (tag.length() > 20) {
                                        if (responseMessage.equals("")) {
                                            responseMessage = "Tags must be 20 characters or less";
                                            success = false;
                                        }
                                        tagList.remove(i);
                                    } else {
                                        //tag is valid, remove the '#' for storage
                                        tagList.set(i, tag.substring(1));
                                    }
                                }
                            }
                            //now have list of alphanumeric tags of 20 chars or less
                            break;
                        }
                    }
                }
                if (!success) {
                    return false;
                }
            } catch (FileUploadException | IOException ex) {
                Logger.getLogger(UploadPostServlet.class.getName()).log(Level.SEVERE, null, ex);
                return false;
            }
        } else {
            request.setAttribute("message", "File upload request not found");
            return false;
        }

        return true;
    }
}