Add file upload support

This commit is contained in:
steve 2013-09-29 18:54:34 +08:00
parent 458d3f43f8
commit fb55e99f7b
20 changed files with 670 additions and 105 deletions

View File

@ -35,8 +35,13 @@
<artifactId>commons.wicket</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>com.pmease</groupId>
<artifactId>commons.jersey</artifactId>
<version>1.0.30</version>
</dependency>
<!-- WICKET -->
<dependency>
<groupId>com.vaynberg.wicket.select2</groupId>
@ -54,7 +59,31 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
<version>1.17</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.imgscalr</groupId>
<artifactId>imgscalr-lib</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>com.codahale.dropwizard</groupId>
<artifactId>dropwizard-jackson</artifactId>
<version>0.7.0-SNAPSHOT</version>
</dependency>
</dependencies>
<repositories>
@ -73,6 +102,18 @@
</snapshots>
<url>http://artifact.pmease.com/</url>
</repository>
<repository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>

View File

@ -1,6 +1,5 @@
package com.pmease.gitop.web;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
@ -17,13 +16,9 @@ import org.apache.wicket.request.Response;
import org.apache.wicket.util.time.Duration;
import org.apache.wicket.util.time.Time;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.io.ByteStreams;
import com.pmease.commons.loader.AppLoader;
import com.pmease.commons.wicket.AbstractWicketConfig;
import com.pmease.gitop.core.manager.ConfigManager;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.web.assets.AssetLocator;
import com.pmease.gitop.web.common.component.avatar.AvatarImageResource;
import com.pmease.gitop.web.common.component.avatar.AvatarImageResourceReference;
@ -135,8 +130,8 @@ public class GitopWebApp extends AbstractWicketConfig {
getSharedResources().add(AvatarImageResourceReference.AVATAR_RESOURCE, new AvatarImageResource());
mountResource("avatars/${type}/${id}", new AvatarImageResourceReference());
mountResource("fileManager", new FileManagerResourceReference(getUploadsDir().getAbsolutePath()));
mountResource("fileUpload", new FileUploadResourceReference(getUploadsDir().getAbsolutePath()));
mountResource("fileManager", new FileManagerResourceReference(SitePaths.get().uploadsDir().getAbsolutePath()));
mountResource("fileUpload", new FileUploadResourceReference(SitePaths.get().uploadsDir().getAbsolutePath()));
}
public boolean isGravatarEnabled() {
@ -146,27 +141,4 @@ public class GitopWebApp extends AbstractWicketConfig {
public boolean isPublicSignupEnabled() {
return true;
}
public File getDataDir() {
String str = AppLoader.getInstance(ConfigManager.class).getStorageSetting().getRepoStorageDir();
return new File(str);
}
public File getSystemAvatarDir() {
return new File(getDataDir(), "avatars");
}
public File getUserAvatarDir(Long id) {
Preconditions.checkNotNull(id, "user id");
return new File(getSystemAvatarDir(), "users/" + id.toString());
}
public File getUserAvatarDir(User user) {
return getUserAvatarDir(user.getId());
}
public File getUploadsDir() {
return new File(getDataDir(), "uploads");
}
}

View File

@ -0,0 +1,56 @@
package com.pmease.gitop.web;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import javax.inject.Inject;
import javax.inject.Singleton;
import com.pmease.commons.bootstrap.Bootstrap;
import com.pmease.commons.loader.AppLoader;
import com.pmease.gitop.core.manager.ConfigManager;
import com.pmease.gitop.core.model.User;
@Singleton
public class SitePaths {
private final ConfigManager configManager;
public static SitePaths get() {
return AppLoader.getInstance(SitePaths.class);
}
@Inject
SitePaths(ConfigManager configManager) {
this.configManager = configManager;
}
public File installDir() {
return Bootstrap.installDir;
}
public File dataDir() {
// TODO: this is not correct, should change repo storage dir to data dir
return new File(configManager.getStorageSetting().getRepoStorageDir());
}
public File avatarsDir() {
return new File(dataDir(), "avatars");
}
public File userAvatarDir(Long id) {
return new File(avatarsDir(), "users/" + checkNotNull(id));
}
public File userAvatarDir(User user) {
return userAvatarDir(checkNotNull(user));
}
public File tempDir() {
return new File(installDir(), "temp");
}
public File uploadsDir() {
return new File(dataDir(), "uploads");
}
}

View File

@ -1,5 +1,6 @@
package com.pmease.gitop.web;
import javax.inject.Singleton;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
@ -11,6 +12,8 @@ import com.pmease.commons.jetty.ServletContextConfigurator;
import com.pmease.commons.loader.AbstractPluginModule;
import com.pmease.commons.wicket.AbstractWicketConfig;
import com.pmease.gitop.web.assets.AssetLocator;
import com.pmease.gitop.web.common.component.fileupload.FileUploadServlet;
import com.pmease.gitop.web.resource.RestResourceModule;
/**
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
@ -24,6 +27,7 @@ public class WebModule extends AbstractPluginModule {
// put your guice bindings here
bind(AbstractWicketConfig.class).to(GitopWebApp.class);
bind(SitePaths.class).in(Singleton.class);
contribute(ServletContextConfigurator.class, new ServletContextConfigurator() {
@ -35,10 +39,13 @@ public class WebModule extends AbstractPluginModule {
ErrorPageErrorHandler errorHandler = (ErrorPageErrorHandler) context.getErrorHandler();
errorHandler.addErrorPage(HttpServletResponse.SC_NOT_FOUND, "/assets/404.html");
servletHolder = context.addServlet(FileUploadServlet.class, "/uploads/*");
}
});
install(new RestResourceModule());
}
}

View File

@ -13,6 +13,7 @@ import com.pmease.commons.loader.AppLoader;
import com.pmease.gitop.core.manager.UserManager;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.web.GitopWebApp;
import com.pmease.gitop.web.SitePaths;
import com.pmease.gitop.web.common.component.avatar.AvatarImage.AvatarImageType;
public class AvatarImageResource extends DynamicImageResource {
@ -30,7 +31,7 @@ public class AvatarImageResource extends DynamicImageResource {
User user = AppLoader.getInstance(UserManager.class).get(id);
if (!Strings.isNullOrEmpty(user.getAvatarUrl())) {
avatarFile = new File(GitopWebApp.get().getUserAvatarDir(id), user.getAvatarUrl());
avatarFile = new File(SitePaths.get().userAvatarDir(id), user.getAvatarUrl());
}
} else {
// Repository project = AppLoader.getInstance(RepositoryManager.class).get(id);

View File

@ -1,43 +1,125 @@
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
<div class="row fileupload-buttonbar">
<div class="span7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="icon-plus icon-white"></i>
<span>Add files...</span>
<input type="file" multiple="true"/>
</span>
<button type="submit" class="btn btn-primary start">
<i class="icon-upload icon-white"></i>
<span>Start upload</span>
<wicket:panel>
<form wicket:id="form" action="/rest/file/upload" method="POST" enctype="multipart/form-data">
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button"> <i
class="glyphicon glyphicon-plus"></i> <span>Add files...</span> <input
type="file" name="files" />
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i> <span>Start
upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i> <span>Cancel
upload</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i> <span>Delete</span>
</button>
<input type="checkbox" class="toggle">
<!-- The loading indicator is shown during file processing -->
<span class="fileupload-loading"></span>
</div>
<!-- The global progress information -->
<div class="col-lg-5 fileupload-progress fade">
<!-- The global progress bar -->
<div class="progress progress-striped active" role="progressbar"
aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar progress-bar-success" style="width: 0%;"></div>
</div>
<!-- The extended global progress information -->
<div class="progress-extended">&nbsp;</div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped">
<tbody class="files"></tbody>
</table>
</form>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td>
<span class="preview"></span>
</td>
<td>
<p class="name">{%=file.name%}</p>
{% if (file.error) { %}
<div><span class="label label-danger">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td>
<p class="size">{%=o.formatFileSize(file.size)%}</p>
{% if (!o.files.error) { %}
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
{% } %}
</td>
<td>
{% if (!o.files.error && !i && !o.options.autoUpload) { %}
<button class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="icon-ban-circle icon-white"></i>
<span>Cancel upload</span>
{% } %}
{% if (!i) { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="icon-trash icon-white"></i>
{% } %}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
<td>
<span class="preview">
{% if (file.thumbnailUrl) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
{% } %}
</span>
</td>
<td>
<p class="name">
{% if (file.url) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
{% } else { %}
<span>{%=file.name%}</span>
{% } %}
</p>
{% if (file.error) { %}
<div><span class="label label-danger">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td>
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
<td>
{% if (file.deleteUrl) { %}
<button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
<input type="checkbox" class="toggle"/>
</div>
<!-- The global progress information -->
<div class="span5 fileupload-progress fade">
<!-- The global progress bar -->
<div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div class="bar" style="width:0%;"></div>
</div>
<!-- The extended global progress information -->
<div class="progress-extended">&#169;</div>
</div>
</div>
<!-- The loading indicator is shown during file processing -->
<div class="fileupload-loading"></div>
<br/>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody></table>
</wicket:panel>
<input type="checkbox" name="delete" value="1" class="toggle">
{% } else { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
</wicket:panel>
</html>

View File

@ -1,5 +1,6 @@
package com.pmease.gitop.web.common.component.fileupload;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.panel.Panel;
/**
@ -13,6 +14,8 @@ public class FileUploadBar extends Panel {
public FileUploadBar(String id) {
super(id);
add(new FileUploadResourceBehavior());
WebMarkupContainer form = new WebMarkupContainer("form");
add(form);
form.add(new FileUploadResourceBehavior());
}
}

View File

@ -5,14 +5,15 @@ import java.util.Map;
import org.apache.wicket.Component;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.util.io.IOUtils;
import org.apache.wicket.util.template.PackageTextTemplate;
import com.pmease.gitop.web.GitopWebApp;
import com.pmease.gitop.web.assets.AssetLocator;
@SuppressWarnings("serial")
@ -20,17 +21,17 @@ public class FileUploadResourceBehavior extends Behavior {
private static final ResourceReference FILEUPLOAD_JS =
new JavaScriptResourceReference(
AssetLocator.class,
"res/js/jquery.file.upload.js");
FileUploadResourceBehavior.class,
"res/js/jquery.fileupload.js");
private static final ResourceReference IFRAME_TRANSPORT_JS =
new JavaScriptResourceReference(
AssetLocator.class,
FileUploadResourceBehavior.class,
"res/js/jquery.iframe-transport.js");
private static final ResourceReference FILEUPLOAD_UI_JS =
new JavaScriptResourceReference(
AssetLocator.class,
FileUploadResourceBehavior.class,
"res/js/jquery.fileupload-ui.js");
/**
@ -55,17 +56,31 @@ public class FileUploadResourceBehavior extends Behavior {
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(CssHeaderItem.forReference(new CssResourceReference(FileUploadResourceBehavior.class, "res/css/jquery.fileupload-ui.css")));
response.render(JavaScriptHeaderItem.forReference(AssetLocator.JQUERY_UI_WIDGET_JS));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/tmpl.min.js")));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/load-image.min.js")));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/jquery.blueimp-gallery.min.js")));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/canvas-to-blob.min.js")));
response.render(JavaScriptHeaderItem.forReference(IFRAME_TRANSPORT_JS));
response.render(JavaScriptHeaderItem.forReference(FILEUPLOAD_JS));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/jquery.fileupload-process.js")));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/jquery.fileupload-audio.js")));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/jquery.fileupload-video.js")));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/jquery.fileupload-image.js")));
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(FileUploadResourceBehavior.class, "res/js/jquery.fileupload-validate.js")));
response.render(JavaScriptHeaderItem.forReference(FILEUPLOAD_UI_JS));
PackageTextTemplate jsTmpl = new PackageTextTemplate(AssetLocator.class, "js/vendor/jquery-file-upload/main.js");
PackageTextTemplate jsTmpl = new PackageTextTemplate(FileUploadResourceBehavior.class,
"res/js/main.js");
try {
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("componentMarkupId", component.getMarkupId());
variables.put("url", component.urlFor(new FileUploadResourceReference(GitopWebApp.get().getUploadsDir().getAbsolutePath()), null));
variables.put("componentId", component.getMarkupId());
variables.put("url", "/rest/file/upload");
variables.put("paramName", PARAM_NAME);
String s = jsTmpl.asString(variables);

View File

@ -13,7 +13,7 @@ import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.util.upload.FileItem;
import com.pmease.gitop.web.GitopWebApp;
import com.pmease.gitop.web.SitePaths;
/**
* A resource reference provides default implementation of
@ -81,7 +81,7 @@ public class FileUploadResourceReference extends ResourceReference {
PageParameters params = new PageParameters();
params.set("filename", fileItem.getName());
CharSequence url = RequestCycle.get().urlFor(
new FileManagerResourceReference(GitopWebApp.get().getUploadsDir().getAbsolutePath()),
new FileManagerResourceReference(SitePaths.get().uploadsDir().getAbsolutePath()),
params);
return url;
}
@ -91,7 +91,7 @@ public class FileUploadResourceReference extends ResourceReference {
params.set("filename", fileItem.getName());
params.set("delete", true);
CharSequence url = RequestCycle.get().urlFor(
new FileManagerResourceReference(GitopWebApp.get().getUploadsDir().getAbsolutePath()),
new FileManagerResourceReference(SitePaths.get().uploadsDir().getAbsolutePath()),
params);
return url;
}

View File

@ -0,0 +1,182 @@
package com.pmease.gitop.web.common.component.fileupload;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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.imgscalr.Scalr;
import org.json.JSONArray;
import org.json.JSONObject;
@SuppressWarnings("serial")
public class FileUploadServlet extends HttpServlet {
static File imgDir = new File("/Users/zhenyu/temp/");
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
if (request.getParameter("getfile") != null
&& !request.getParameter("getfile").isEmpty()) {
File file = new File(imgDir, request.getParameter("getfile"));
if (file.exists()) {
int bytes = 0;
ServletOutputStream op = response.getOutputStream();
response.setContentType(getMimeType(file));
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "inline; filename=\""
+ file.getName() + "\"");
byte[] bbuf = new byte[1024];
DataInputStream in = new DataInputStream(new FileInputStream(
file));
while ((in != null) && ((bytes = in.read(bbuf)) != -1)) {
op.write(bbuf, 0, bytes);
}
in.close();
op.flush();
op.close();
}
} else if (request.getParameter("delfile") != null
&& !request.getParameter("delfile").isEmpty()) {
File file = new File(imgDir, request.getParameter("delfile"));
if (file.exists()) {
file.delete(); // TODO:check and report success
}
} else if (request.getParameter("getthumb") != null
&& !request.getParameter("getthumb").isEmpty()) {
File file = new File(imgDir, request.getParameter("getthumb"));
if (file.exists()) {
System.out.println(file.getAbsolutePath());
String mimetype = getMimeType(file);
if (mimetype.endsWith("png") || mimetype.endsWith("jpeg")
|| mimetype.endsWith("jpg") || mimetype.endsWith("gif")) {
BufferedImage im = ImageIO.read(file);
if (im != null) {
BufferedImage thumb = Scalr.resize(im, 75);
ByteArrayOutputStream os = new ByteArrayOutputStream();
if (mimetype.endsWith("png")) {
ImageIO.write(thumb, "PNG", os);
response.setContentType("image/png");
} else if (mimetype.endsWith("jpeg")) {
ImageIO.write(thumb, "jpg", os);
response.setContentType("image/jpeg");
} else if (mimetype.endsWith("jpg")) {
ImageIO.write(thumb, "jpg", os);
response.setContentType("image/jpeg");
} else {
ImageIO.write(thumb, "GIF", os);
response.setContentType("image/gif");
}
ServletOutputStream srvos = response.getOutputStream();
response.setContentLength(os.size());
response.setHeader("Content-Disposition",
"inline; filename=\"" + file.getName() + "\"");
os.writeTo(srvos);
srvos.flush();
srvos.close();
}
}
} // TODO: check and report success
} else {
PrintWriter writer = response.getWriter();
writer.write("call POST with multipart form data");
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*
*/
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
if (!ServletFileUpload.isMultipartContent(request)) {
throw new IllegalArgumentException(
"Request is not multipart, please 'multipart/form-data' enctype for your form.");
}
ServletFileUpload uploadHandler = new ServletFileUpload(new DiskFileItemFactory());
PrintWriter writer = response.getWriter();
response.setContentType("application/json");
JSONArray json = new JSONArray();
try {
List<FileItem> items = uploadHandler.parseRequest(request);
for (FileItem item : items) {
if (!item.isFormField()) {
File file = new File(imgDir, item.getName());
item.write(file);
JSONObject jsono = new JSONObject();
jsono.put("name", item.getName());
jsono.put("size", item.getSize());
jsono.put("url", "UploadServlet?getfile=" + item.getName());
jsono.put("thumbnail_url",
"UploadServlet?getthumb=" + item.getName());
jsono.put("delete_url",
"UploadServlet?delfile=" + item.getName());
jsono.put("delete_type", "GET");
json.put(jsono);
System.out.println(json.toString());
}
}
} catch (FileUploadException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
writer.write(json.toString());
writer.close();
}
}
private String getMimeType(File file) {
String mimetype = "";
if (file.exists()) {
if (getSuffix(file.getName()).equalsIgnoreCase("png")) {
mimetype = "image/png";
} else if (getSuffix(file.getName()).equalsIgnoreCase("jpg")) {
mimetype = "image/jpg";
} else if (getSuffix(file.getName()).equalsIgnoreCase("jpeg")) {
mimetype = "image/jpeg";
} else if (getSuffix(file.getName()).equalsIgnoreCase("gif")) {
mimetype = "image/gif";
} else {
javax.activation.MimetypesFileTypeMap mtMap = new javax.activation.MimetypesFileTypeMap();
mimetype = mtMap.getContentType(file);
}
}
return mimetype;
}
private String getSuffix(String filename) {
String suffix = "";
int pos = filename.lastIndexOf('.');
if (pos > 0 && pos < filename.length() - 1) {
suffix = filename.substring(pos + 1);
}
return suffix;
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,68 @@
@charset "UTF-8";
/*
* jQuery File Upload UI Plugin CSS 8.8.1
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
.fileinput-button {
position: relative;
overflow: hidden;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
filter: alpha(opacity=0);
transform: translate(-300px, 0) scale(4);
font-size: 23px;
direction: ltr;
cursor: pointer;
}
.fileupload-buttonbar .btn,
.fileupload-buttonbar .toggle {
margin-bottom: 5px;
}
.progress-animated .progress-bar,
.progress-animated .bar {
background: url(../img/progressbar.gif) !important;
filter: none;
}
.fileupload-loading {
float: right;
width: 32px;
height: 32px;
background: url(../img/loading.gif) center no-repeat;
background-size: contain;
display: none;
}
.fileupload-processing .fileupload-loading {
display: block;
}
.files audio,
.files video {
max-width: 300px;
}
@media (max-width: 767px) {
.fileupload-buttonbar .toggle,
.files .toggle,
.files .btn span {
display: none;
}
.files .name {
width: 80px;
word-wrap: break-word;
}
.files audio,
.files video {
max-width: 80px;
}
}

View File

@ -0,0 +1 @@
!function(t){"use strict";var e=t.HTMLCanvasElement&&t.HTMLCanvasElement.prototype,n=t.Blob&&function(){try{return Boolean(new Blob)}catch(t){return!1}}(),o=n&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(t){return!1}}(),r=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,i=(n||r)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(t){var e,i,a,l,u,B;for(e=t.split(",")[0].indexOf("base64")>=0?atob(t.split(",")[1]):decodeURIComponent(t.split(",")[1]),i=new ArrayBuffer(e.length),a=new Uint8Array(i),l=0;l<e.length;l+=1)a[l]=e.charCodeAt(l);return u=t.split(",")[0].split(":")[1].split(";")[0],n?new Blob([o?a:i],{type:u}):(B=new r,B.append(i),B.getBlob(u))};t.HTMLCanvasElement&&!e.toBlob&&(e.mozGetAsFile?e.toBlob=function(t,n,o){o&&e.toDataURL&&i?t(i(this.toDataURL(n,o))):t(this.mozGetAsFile("blob",n))}:e.toDataURL&&i&&(e.toBlob=function(t,e,n){t(i(this.toDataURL(e,n)))})),"function"==typeof define&&define.amd?define(function(){return i}):t.dataURLtoBlob=i}(this);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,26 +1,41 @@
/*
* jQuery File Upload Plugin JS Example 8.8.2
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
/*jslint nomen: true, regexp: true */
/*global $, window, blueimp */
$(function () {
'use strict';
$('#${componentMarkupId}').fileupload({
url: '${url}',
paramName: '${paramName}',
singleFileUploads: true,
maxFileSize: 5000000,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
process: [
{
action: 'load',
fileTypes: /^image\/(gif|jpeg|png)$/,
maxFileSize: 20000000 // 20MB
},
{
action: 'resize',
maxWidth: 1440,
maxHeight: 900
},
{
action: 'save'
}
]
// Initialize the jQuery File Upload widget:
$('#${componentId}').fileupload({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: '${url}'
});
});
// Load existing files:
$('#${componentId}').addClass('fileupload-processing');
$.ajax({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: $('#${componentId}').fileupload('option', 'url'),
dataType: 'json',
context: $('#${componentId}')[0]
}).always(function () {
$(this).removeClass('fileupload-processing');
}).done(function (result) {
console.log('done');
$(this).fileupload('option', 'done')
.call(this, null, {result: result});
});
});

View File

@ -1 +1 @@
(function(a){"use strict";var b=function(a,c){var d=/[^\w\-\.:]/.test(a)?new Function(b.arg+",tmpl","var _e=tmpl.encode"+b.helper+",_s='"+a.replace(b.regexp,b.func)+"';return _s;"):b.cache[a]=b.cache[a]||b(b.load(a));return c?d(c,b):function(a){return d(a,b)}};b.cache={},b.load=function(a){return document.getElementById(a).innerHTML},b.regexp=/([\s'\\])(?![^%]*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,b.func=function(a,b,c,d,e,f){if(b)return{"\n":"\\n","\r":"\\r","\t":"\\t"," ":" "}[a]||"\\"+a;if(c)return c==="="?"'+_e("+d+")+'":"'+("+d+"||'')+'";if(e)return"';";if(f)return"_s+='"},b.encReg=/[<>&"'\x00]/g,b.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","'":"&#39;"},b.encode=function(a){return String(a||"").replace(b.encReg,function(a){return b.encMap[a]||""})},b.arg="o",b.helper=",print=function(s,e){_s+=e&&(s||'')||_e(s);},include=function(s,d){_s+=tmpl(s,d);}",typeof define=="function"&&define.amd?define(function(){return b}):a.tmpl=b})(this);
!function(e){"use strict";var n=function(e,t){var c=/[^\w\-\.:]/.test(e)?new Function(n.arg+",tmpl","var _e=tmpl.encode"+n.helper+",_s='"+e.replace(n.regexp,n.func)+"';return _s;"):n.cache[e]=n.cache[e]||n(n.load(e));return t?c(t,n):function(e){return c(e,n)}};n.cache={},n.load=function(e){return document.getElementById(e).innerHTML},n.regexp=/([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,n.func=function(e,n,t,c,r,u){return n?{"\n":"\\n","\r":"\\r"," ":"\\t"," ":" "}[n]||"\\"+n:t?"="===t?"'+_e("+c+")+'":"'+("+c+"==null?'':"+c+")+'":r?"';":u?"_s+='":void 0},n.encReg=/[<>&"'\x00]/g,n.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","'":"&#39;"},n.encode=function(e){return(null==e?"":""+e).replace(n.encReg,function(e){return n.encMap[e]||""})},n.arg="o",n.helper=",print=function(s,e){_s+=e?(s==null?'':s):_e(s);},include=function(s,d){_s+=tmpl(s,d);}","function"==typeof define&&define.amd?define(function(){return n}):e.tmpl=n}(this);

View File

@ -2,7 +2,6 @@
<wicket:extend>
<div class="container">
<h1>Hello, Gitop!</h1>
<h3>Upload Test</h3>
<div wicket:id="upload"></div>
</div>

View File

@ -0,0 +1,12 @@
package com.pmease.gitop.web.resource;
import com.google.inject.AbstractModule;
public class RestResourceModule extends AbstractModule {
@Override
protected void configure() {
bind(TestResource.class);
}
}

View File

@ -0,0 +1,108 @@
package com.pmease.gitop.web.resource;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.codahale.dropwizard.jackson.Jackson;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.pmease.gitop.web.SitePaths;
@Path("/file")
public class TestResource {
private static final String SUCCESS_RESPONSE = "Successful";
private static final String FAILED_RESPONSE = "Failed";
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@Context HttpServletRequest request) throws JsonProcessingException {
String candidateName = null;
File uploadDir = SitePaths.get().uploadsDir();
Result result = new Result();
// checks whether there is a file upload request or not
if (ServletFileUpload.isMultipartContent(request)) {
final FileItemFactory factory = new DiskFileItemFactory();
final ServletFileUpload fileUpload = new ServletFileUpload(factory);
try {
/*
* parseRequest returns a list of FileItem but in old
* (pre-java5) style
*/
final List<FileItem> items = fileUpload.parseRequest(request);
if (items != null) {
final Iterator<FileItem> iter = items.iterator();
while (iter.hasNext()) {
final FileItem item = iter.next();
final String itemName = item.getName();
final String fieldName = item.getFieldName();
final String fieldValue = item.getString();
if (item.isFormField()) {
candidateName = fieldValue;
System.out.println("Field Name: " + fieldName
+ ", Field Value: " + fieldValue);
System.out.println("Candidate Name: "
+ candidateName);
} else {
final File savedFile = new File(uploadDir, itemName);
System.out.println("Saving the file: "
+ savedFile.getName());
item.write(savedFile);
UploadFile f = new UploadFile();
f.name = savedFile.getName();
f.size = savedFile.length();
result.files.add(f);
}
}
}
} catch (FileUploadException fue) {
fue.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
ObjectMapper mapper = Jackson.newObjectMapper();
String str = mapper.writeValueAsString(result);
System.out.println("Returned Response Status: " + str);
return Response.ok().entity(str).build();
}
static class Result {
@JsonProperty
List<UploadFile> files = Lists.newArrayList();
}
static class UploadFile {
@JsonProperty
String name;
@JsonProperty
long size;
}
}