Skip to content

Commit

Permalink
For #85 - implemented pictures uploading
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalidze committed May 21, 2015
1 parent f9d1eba commit aaf842f
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
import com.sencha.gxt.widget.core.client.container.BorderLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.SubmitCompleteEvent;
import com.sencha.gxt.widget.core.client.form.FileUploadField;
import com.sencha.gxt.widget.core.client.form.FormPanel;
import org.traccar.web.shared.model.DeviceIconType;
import org.traccar.web.shared.model.Position;

Expand Down Expand Up @@ -82,6 +85,9 @@ public interface DeviceMarkerHandler {
@UiField(provided = true)
BorderLayoutContainer.BorderLayoutData eastData;

@UiField(provided = true)
BorderLayoutContainer.BorderLayoutData southData;

@UiField
VerticalLayoutContainer panelImages;

Expand All @@ -94,6 +100,12 @@ public interface DeviceMarkerHandler {
@UiField
Image offlineImage;

@UiField
FormPanel form;

@UiField
FileUploadField fileToImport;

final DeviceMarkerHandler handler;

static abstract class Marker {
Expand Down Expand Up @@ -200,14 +212,25 @@ public void onSelection(SelectionEvent<Marker> event) {
});

eastData = new BorderLayoutContainer.BorderLayoutData(85);
eastData.setSplit(true);
eastData.setSplit(false);
eastData.setMargins(new Margins(5, 0, 0, 0));

centerData = new BorderLayoutContainer.BorderLayoutData();
centerData.setMargins(new Margins(0, 5, 0, 0));

southData = new BorderLayoutContainer.BorderLayoutData(32);
southData.setSplit(false);
southData.setMargins(new Margins(5, 0, 0, 5));

uiBinder.createAndBindUi(this);

form.addSubmitCompleteHandler(new SubmitCompleteEvent.SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
new LogViewDialog(event.getResults()).show();
}
});

view.getSelectionModel().select(selectedMarker, false);

updateImages();
Expand All @@ -233,6 +256,11 @@ public void onCancelClicked(SelectEvent event) {
hide();
}

@UiHandler("uploadButton")
public void onUploadClicked(SelectEvent event) {
form.submit();
}

private void updateImages() {
Marker marker = view.getSelectionModel().getSelectedItem();
if (marker == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container"
xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button" xmlns:field="http://www.w3.org/1999/html">
xmlns:form="urn:import:com.sencha.gxt.widget.core.client.form"
xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button">

<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="verticalLayoutData">
<ui:attributes width="1" height="-1" />
Expand All @@ -18,12 +19,17 @@
<ui:attributes width="-1" height="-1" margins="{imageMargins}" />
</ui:with>

<ui:with type="com.sencha.gxt.widget.core.client.container.HorizontalLayoutContainer.HorizontalLayoutData" field="horizontalLayoutData">
<ui:attributes width="-1" height="-1" />
</ui:with>

<ui:with type="com.sencha.gxt.widget.core.client.container.BorderLayoutContainer.BorderLayoutData" field="centerData" />
<ui:with type="com.sencha.gxt.widget.core.client.container.BorderLayoutContainer.BorderLayoutData" field="eastData" />
<ui:with type="com.sencha.gxt.widget.core.client.container.BorderLayoutContainer.BorderLayoutData" field="southData" />

<ui:with field='i18n' type='org.traccar.web.client.i18n.Messages' />

<gxt:Window ui:field="window" pixelSize="386, 280" modal="true" headingText="{i18n.markers}" focusWidget="{saveButton}">
<gxt:Window ui:field="window" pixelSize="386, 310" modal="true" headingText="{i18n.markers}" focusWidget="{saveButton}">
<container:BorderLayoutContainer ui:field="con" borders="true">
<container:center layoutData="{centerData}">
<gxt:ListView ui:field="view"/>
Expand All @@ -50,6 +56,22 @@
</container:child>
</container:VerticalLayoutContainer>
</container:east>
<container:south layoutData="{southData}">
<form:FormPanel action="/traccar/p/MARKER" method="POST" encoding="MULTIPART" ui:field="form">
<container:HorizontalLayoutContainer>
<container:child layoutData="{horizontalLayoutData}">
<form:FieldLabel text="{i18n.fileToImport}">
<form:widget>
<form:FileUploadField ui:field="fileToImport" />
</form:widget>
</form:FieldLabel>
</container:child>
<container:child layoutData="{horizontalLayoutData}">
<button:TextButton ui:field="uploadButton" text="Upload" />
</container:child>
</container:HorizontalLayoutContainer>
</form:FormPanel>
</container:south>
</container:BorderLayoutContainer>

<gxt:button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ protected void configureServlets() {
serve("/traccar/export/*").with(ExportServlet.class);
serve("/traccar/import/*").with(ImportServlet.class);
serve("/traccar/s/login").with(LoginServlet.class);
serve("/traccar/p/*").with(PicturesServlet.class);

UserCheck userCheck = new UserCheck();
requestInjection(userCheck);
Expand Down
113 changes: 113 additions & 0 deletions src/main/java/org/traccar/web/server/model/PicturesServlet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright 2015 Vitaly Litvak ([email protected])
*
* 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.
*/
package org.traccar.web.server.model;

import com.google.inject.persist.Transactional;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.traccar.web.shared.model.Picture;
import org.traccar.web.shared.model.PictureType;

import javax.imageio.ImageIO;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;

@Singleton
public class PicturesServlet extends HttpServlet {
@Inject
private Provider<EntityManager> entityManager;
@Inject
protected Logger logger;

@Transactional(rollbackOn = { IOException.class, RuntimeException.class })
@RequireUser
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PictureType pictureType;
try {
pictureType = PictureType.valueOf(req.getPathInfo().substring(1));
} catch (IllegalArgumentException iae) {
logger.log(Level.WARNING, "Incorrect picture type: " + req.getPathInfo(), iae);
resp.getWriter().write("Unsupported picture type: " + req.getPathInfo());
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}

ServletFileUpload servletFileUpload = new ServletFileUpload();

OutputStream os = null;
File file = null;
try {
FileItemIterator fileItemIterator = servletFileUpload.getItemIterator(req);
while (fileItemIterator.hasNext()) {
file = File.createTempFile("uploaded", ".image");
file.deleteOnExit();
os = new BufferedOutputStream(new FileOutputStream(file));
IOUtils.copy(fileItemIterator.next().openStream(), os);
os.flush();
os.close();
if (file.length() > pictureType.getMaxFileSize()) {
resp.getWriter().write("File is too big. Max size is " + pictureType.getMaxFileSize() + " bytes.");
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}

BufferedImage image = ImageIO.read(file);
if (image == null) {
resp.getWriter().write("This is not an image.");
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}

if (image.getWidth() > pictureType.getMaxWidth() || image.getHeight() > pictureType.getMaxHeight()) {
resp.getWriter().write("Image dimesions are too big. Max dimensions are: " + pictureType.getMaxWidth() + "x" + pictureType.getMaxHeight());
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}

Picture picture = new Picture();
picture.setType(pictureType);
picture.setWidth(image.getWidth());
picture.setHeight(image.getHeight());
picture.setData(FileUtils.readFileToByteArray(file));
entityManager.get().persist(picture);
}
} catch (FileUploadException fue) {
logger.log(Level.WARNING, fue.getLocalizedMessage(), fue);
throw new IOException(fue);
} catch (IOException ioex) {
logger.log(Level.WARNING, ioex.getLocalizedMessage(), ioex);
throw ioex;
} finally {
IOUtils.closeQuietly(os);
FileUtils.deleteQuietly(file);
}
}
}
19 changes: 19 additions & 0 deletions src/main/java/org/traccar/web/shared/model/Picture.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ public void setData(byte[] data) {
this.data = data;
}

private int width;
private int height;

public int getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package org.traccar.web.shared.model;

public enum PictureType {
MARKER(20 * 1024, 70, 30), DEVICE_PHOTO(300 * 1024, 1024, 768);
MARKER(20 * 1024, 70, 40), DEVICE_PHOTO(300 * 1024, 1024, 768);

final int maxFileSize;
final int maxWidth;
Expand Down

0 comments on commit aaf842f

Please sign in to comment.