From b3bdc5bb7db30d9334c1c8ee7fe3ee7d582b4a80 Mon Sep 17 00:00:00 2001 From: Charles Lovett Date: Tue, 9 Jun 2020 18:14:20 +0000 Subject: [PATCH] add blobstore to webapp --- .../google/sps/servlets/BlobUrlServlet.java | 41 ++++++++++ .../com/google/sps/servlets/DataServlet.java | 16 ++-- .../sps/servlets/FileHandlerServlet.java | 80 +++++++++++++++++++ portfolio/src/main/webapp/index.html | 23 +++--- portfolio/src/main/webapp/script.js | 29 ++++--- 5 files changed, 163 insertions(+), 26 deletions(-) create mode 100644 portfolio/src/main/java/com/google/sps/servlets/BlobUrlServlet.java create mode 100644 portfolio/src/main/java/com/google/sps/servlets/FileHandlerServlet.java diff --git a/portfolio/src/main/java/com/google/sps/servlets/BlobUrlServlet.java b/portfolio/src/main/java/com/google/sps/servlets/BlobUrlServlet.java new file mode 100644 index 0000000..e6e4113 --- /dev/null +++ b/portfolio/src/main/java/com/google/sps/servlets/BlobUrlServlet.java @@ -0,0 +1,41 @@ +// Copyright 2019 Google LLC +// +// 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 +// +// https://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. + +package com.google.sps.servlets; + +import com.google.appengine.api.blobstore.BlobstoreService; +import com.google.appengine.api.blobstore.BlobstoreServiceFactory; +import java.io.IOException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * When the fetch() function requests the /blobstore-upload-url URL, the content of the response is + * the URL that allows a user to upload a file to Blobstore. If this sounds confusing, try running a + * dev server and navigating to /blobstore-upload-url to see the Blobstore URL. + */ +@WebServlet("/blob-url") +public class BlobUrlServlet extends HttpServlet { + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + + BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); + String uploadUrl = blobstoreService.createUploadUrl("/file-handler"); + + response.setContentType("text/html"); + response.getWriter().println(uploadUrl); + } +} \ No newline at end of file diff --git a/portfolio/src/main/java/com/google/sps/servlets/DataServlet.java b/portfolio/src/main/java/com/google/sps/servlets/DataServlet.java index 471b744..ff2e936 100644 --- a/portfolio/src/main/java/com/google/sps/servlets/DataServlet.java +++ b/portfolio/src/main/java/com/google/sps/servlets/DataServlet.java @@ -23,7 +23,8 @@ import com.google.gson.Gson; import com.google.sps.data.Post; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -32,7 +33,7 @@ /** Servlet that returns some example content. TODO: modify this file to handle comments data */ @WebServlet("/Comments") public class DataServlet extends HttpServlet { - private int max=5; + private int maxNumberOfComments=5; private static final String COMMENTS_ENTITY_NAME = "Comments"; private static final String TIMESTAMP_PROPERTY_KEY = "timestamp"; private static final String COMMENT_PROPERTY_KEY = "comment"; @@ -46,7 +47,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro PreparedQuery results = datastore.prepare(query); List comments = new ArrayList<>(); - FetchOptions fetchOptions = FetchOptions.Builder.withLimit(max); + FetchOptions fetchOptions = FetchOptions.Builder.withLimit(maxNumberOfComments); for (Entity entity : results.asIterable(fetchOptions)) { long id = entity.getKey().getId(); String comment = (String) entity.getProperty(COMMENT_PROPERTY_KEY); @@ -68,7 +69,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr String userComment = request.getParameter(COMMENT_PARAMETER_NAME); long timestamp = System.currentTimeMillis(); String maxString = request.getParameter(MAX_COMMENTS_PARAMETER_NAME); - if (userComment != null) { + if (userComment != null ) { Entity taskEntity = new Entity(COMMENTS_ENTITY_NAME); taskEntity.setProperty(COMMENT_PROPERTY_KEY, userComment); taskEntity.setProperty(TIMESTAMP_PROPERTY_KEY, timestamp); @@ -77,11 +78,10 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr datastore.put(taskEntity); } else if (maxString != null) { try { - max = Integer.parseInt(maxString); - + maxNumberOfComments = Integer.parseInt(maxString); } catch (NumberFormatException e) { - System.out.println("Could not convert to int: " + maxString); - max = 1; + System.out.println("Could not convert to int|" + maxString+"|"); + maxNumberOfComments = 1; } } diff --git a/portfolio/src/main/java/com/google/sps/servlets/FileHandlerServlet.java b/portfolio/src/main/java/com/google/sps/servlets/FileHandlerServlet.java new file mode 100644 index 0000000..9f16a74 --- /dev/null +++ b/portfolio/src/main/java/com/google/sps/servlets/FileHandlerServlet.java @@ -0,0 +1,80 @@ +package com.google.sps.servlets; + +import com.google.appengine.api.blobstore.BlobInfo; +import com.google.appengine.api.blobstore.BlobInfoFactory; +import com.google.appengine.api.blobstore.BlobKey; +import com.google.appengine.api.blobstore.BlobstoreService; +import com.google.appengine.api.blobstore.BlobstoreServiceFactory; +import com.google.appengine.api.images.ImagesService; +import com.google.appengine.api.images.ImagesServiceFactory; +import com.google.appengine.api.images.ServingUrlOptions; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; +import java.util.Map; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * When the user submits the form, Blobstore processes the file upload and then forwards the request + * to this servlet. This servlet can then process the request using the file URL we get from + * Blobstore. + */ +@WebServlet("/file-handler") +public class FileHandlerServlet extends HttpServlet { + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { + + // Get the URL of the image that the user uploaded to Blobstore. + String imageUrl = getUploadedFileUrl(request, "images"); + + //Will change when walkthrough is finished + System.out.println(imageUrl); + PrintWriter out = response.getWriter(); + out.println("

Here's the image you uploaded:

"); + out.println(""); + out.println(""); + out.println(""); + + + } + /** Returns a URL that points to the uploaded file, or null if the user didn't upload a file. */ + private String getUploadedFileUrl(HttpServletRequest request, String formInputElementName) { + BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); + Map> blobs = blobstoreService.getUploads(request); + List blobKeys = blobs.get("images"); + + // User submitted form without selecting a file, so we can't get a URL. (dev server) + if (blobKeys == null || blobKeys.isEmpty()) { + return null; + } + + // Our form only contains a single file input, so get the first index. + BlobKey blobKey = blobKeys.get(0); + + // User submitted form without selecting a file, so we can't get a URL. (live server) + BlobInfo blobInfo = new BlobInfoFactory().loadBlobInfo(blobKey); + if (blobInfo.getSize() == 0) { + blobstoreService.delete(blobKey); + System.out.println("Nothing here"); + return null; + } + + + // Use ImagesService to get a URL that points to the uploaded file. + ImagesService imagesService = ImagesServiceFactory.getImagesService(); + ServingUrlOptions options = ServingUrlOptions.Builder.withBlobKey(blobKey); + + + try { + URL url = new URL(imagesService.getServingUrl(options)); + return url.getPath(); + } catch (MalformedURLException e) { + return imagesService.getServingUrl(options); + } + } +} \ No newline at end of file diff --git a/portfolio/src/main/webapp/index.html b/portfolio/src/main/webapp/index.html index 897a6d9..0cbd16c 100644 --- a/portfolio/src/main/webapp/index.html +++ b/portfolio/src/main/webapp/index.html @@ -7,31 +7,36 @@ - -
+ +

Charles Lovett's Portfolio

- -

Post a comment

- +

- - +

Maxium comments

- +

- +


    +
    +

    +

    Upload Image

    + +

    + +
    +

    This Portfolio contains my life growing up and during college. Hope you enjoy learning a little bit about me.

    Real Quick if you want to know some fun facts about me press the button below:

    diff --git a/portfolio/src/main/webapp/script.js b/portfolio/src/main/webapp/script.js index 75bac8c..dae0825 100644 --- a/portfolio/src/main/webapp/script.js +++ b/portfolio/src/main/webapp/script.js @@ -31,15 +31,18 @@ function addRandomFunFact() { } function getComments() { + + fetch('/Comments').then(response => response.json()).then((com) => { const commentList = document.getElementById('fetch-comment'); com.forEach((comment) => { - commentList.appendChild(createTaskElement(comment)); + commentList.appendChild(createCommentElement(comment)); }) }); + getImage(); } -function createTaskElement(comment) { +function createCommentElement(comment) { const taskElement = document.createElement('li'); taskElement.className = 'comment'; @@ -50,7 +53,7 @@ function createTaskElement(comment) { const deleteButtonElement = document.createElement('button'); deleteButtonElement.innerText = 'Delete'; deleteButtonElement.addEventListener('click', () => { - deleteTask(comment); + deleteComment(comment); // Remove the task from the DOM. taskElement.remove(); @@ -62,13 +65,21 @@ function createTaskElement(comment) { } -function createListElement(text) { - const liElement = document.createElement('li'); - liElement.innerText = text; - return liElement; -} -function deleteTask(task) { +function deleteComment(task) { const params = new URLSearchParams(); params.append('id', task.id); fetch('/delete-data', {method: 'POST', body: params}); } + +function getImage(){ + + fetch('/blob-url') + .then((response) => { + return response.text(); + }) + .then((imageUploadUrl) => { + const messageForm = document.getElementById('uploaded-image'); + messageForm.action = imageUploadUrl; + // messageForm.classList.remove('hidden'); + }); +}