/*
* Copyright 2009-2010 the original author or authors.
*
* 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.springframework.batch.admin.web;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.admin.service.FileInfo;
import org.springframework.batch.admin.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.HtmlUtils;
/**
* Controller for uploading and managing files.
*
* @author Dave Syer
*
*/
@Controller
public class FileController {
private static Log logger = LogFactory.getLog(FileController.class);
private FileService fileService;
/**
* The service used to manage file lists and uploads.
*
* @param fileService the {@link FileService} to set
*/
@Autowired
public void setFileService(FileService fileService) {
this.fileService = fileService;
}
@RequestMapping(value = "/files", method = RequestMethod.POST)
public String uploadRequest(@RequestParam String path, @RequestParam MultipartFile file, ModelMap model,
@RequestParam(defaultValue = "0") int startFile, @RequestParam(defaultValue = "20") int pageSize,
@ModelAttribute("date") Date date, Errors errors) throws Exception {
return upload(path, file, model, startFile, pageSize, date, errors);
}
@RequestMapping(value = "/files/{path}", method = RequestMethod.POST)
public String upload(@PathVariable String path, @RequestParam MultipartFile file, ModelMap model,
@RequestParam(defaultValue = "0") int startFile, @RequestParam(defaultValue = "20") int pageSize,
@ModelAttribute("date") Date date, Errors errors) throws Exception {
String originalFilename = file.getOriginalFilename();
if (file.isEmpty()) {
errors.reject("file.upload.empty", new Object[] { originalFilename },
"File upload was empty for filename=[" + HtmlUtils.htmlEscape(originalFilename) + "]");
list(model, startFile, pageSize);
return "files";
}
try {
FileInfo dest = fileService.createFile(path + "/" + originalFilename);
file.transferTo(fileService.getResource(dest.getPath()).getFile());
fileService.publish(dest);
model.put("uploaded", dest.getPath());
}
catch (IOException e) {
errors.reject("file.upload.failed", new Object[] { originalFilename }, "File upload failed for "
+ HtmlUtils.htmlEscape(originalFilename));
}
catch (Exception e) {
String message = "File upload failed downstream processing for "
+ HtmlUtils.htmlEscape(originalFilename);
if (logger.isDebugEnabled()) {
logger.debug(message, e);
} else {
logger.info(message);
}
errors.reject("file.upload.failed.downstream", new Object[] { originalFilename }, message);
}
if (errors.hasErrors()) {
list(model, startFile, pageSize);
return "files";
}
return "redirect:files";
}
@RequestMapping(value = "/files", method = RequestMethod.GET)
public void list(ModelMap model, @RequestParam(defaultValue = "0") int startFile,
@RequestParam(defaultValue = "20") int pageSize) throws Exception {
List<FileInfo> files = fileService.getFiles(startFile, pageSize);
Collections.sort(files);
model.put("files", files);
}
@RequestMapping(value = "/files/**", method = RequestMethod.GET)
public String get(HttpServletRequest request, HttpServletResponse response, ModelMap model,
@RequestParam(defaultValue = "0") int startFile, @RequestParam(defaultValue = "20") int pageSize,
@ModelAttribute("date") Date date, Errors errors) throws Exception {
list(model, startFile, pageSize);
String path = request.getPathInfo().substring("/files/".length());
Resource file = fileService.getResource(path);
if (file == null || !file.exists()) {
errors.reject("file.download.missing", new Object[] { path },
"File download failed for missing file at path=" + HtmlUtils.htmlEscape(path));
return "files";
}
response.setContentType("application/octet-stream");
try {
FileCopyUtils.copy(file.getInputStream(), response.getOutputStream());
}
catch (IOException e) {
errors.reject("file.download.failed", new Object[] { path }, "File download failed for path=" + HtmlUtils.htmlEscape(path));
logger.info("File download failed for path=" + path, e);
return "files";
}
return null;
}
@RequestMapping(value = "/files", method = RequestMethod.DELETE)
public String delete(ModelMap model, @RequestParam(defaultValue = "**") String pattern) throws Exception {
int deletedCount = fileService.delete(pattern);
model.put("files", new ArrayList<String>());
model.put("deletedCount", deletedCount);
return "redirect:files";
}
}