View Javadoc
1   /*
2    * Copyright 2009-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.springframework.batch.admin.web;
17  
18  import java.io.IOException;
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.Date;
22  import java.util.List;
23  
24  import javax.servlet.http.HttpServletRequest;
25  import javax.servlet.http.HttpServletResponse;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.springframework.batch.admin.service.FileInfo;
30  import org.springframework.batch.admin.service.FileService;
31  import org.springframework.beans.factory.annotation.Autowired;
32  import org.springframework.core.io.Resource;
33  import org.springframework.stereotype.Controller;
34  import org.springframework.ui.ModelMap;
35  import org.springframework.util.FileCopyUtils;
36  import org.springframework.validation.Errors;
37  import org.springframework.web.bind.annotation.ModelAttribute;
38  import org.springframework.web.bind.annotation.PathVariable;
39  import org.springframework.web.bind.annotation.RequestMapping;
40  import org.springframework.web.bind.annotation.RequestMethod;
41  import org.springframework.web.bind.annotation.RequestParam;
42  import org.springframework.web.multipart.MultipartFile;
43  import org.springframework.web.util.HtmlUtils;
44  
45  /**
46   * Controller for uploading and managing files.
47   * 
48   * @author Dave Syer
49   * 
50   */
51  @Controller
52  public class FileController {
53  
54  	private static Log logger = LogFactory.getLog(FileController.class);
55  
56  	private FileService fileService;
57  
58  	/**
59  	 * The service used to manage file lists and uploads.
60  	 * 
61  	 * @param fileService the {@link FileService} to set
62  	 */
63  	@Autowired
64  	public void setFileService(FileService fileService) {
65  		this.fileService = fileService;
66  	}
67  
68  	@RequestMapping(value = "/files", method = RequestMethod.POST)
69  	public String uploadRequest(@RequestParam String path, @RequestParam MultipartFile file, ModelMap model,
70  			@RequestParam(defaultValue = "0") int startFile, @RequestParam(defaultValue = "20") int pageSize,
71  			@ModelAttribute("date") Date date, Errors errors) throws Exception {
72  		return upload(path, file, model, startFile, pageSize, date, errors);
73  	}
74  
75  	@RequestMapping(value = "/files/{path}", method = RequestMethod.POST)
76  	public String upload(@PathVariable String path, @RequestParam MultipartFile file, ModelMap model,
77  			@RequestParam(defaultValue = "0") int startFile, @RequestParam(defaultValue = "20") int pageSize,
78  			@ModelAttribute("date") Date date, Errors errors) throws Exception {
79  
80  		String originalFilename = file.getOriginalFilename();
81  		if (file.isEmpty()) {
82  			errors.reject("file.upload.empty", new Object[] { originalFilename },
83  					"File upload was empty for filename=[" + HtmlUtils.htmlEscape(originalFilename) + "]");
84  			list(model, startFile, pageSize);
85  			return "files";
86  		}
87  
88  		try {
89  			FileInfo dest = fileService.createFile(path + "/" + originalFilename);
90  			file.transferTo(fileService.getResource(dest.getPath()).getFile());
91  			fileService.publish(dest);
92  			model.put("uploaded", dest.getPath());
93  		}
94  		catch (IOException e) {
95  			errors.reject("file.upload.failed", new Object[] { originalFilename }, "File upload failed for "
96  					+ HtmlUtils.htmlEscape(originalFilename));
97  		}
98  		catch (Exception e) {
99  			String message = "File upload failed downstream processing for "
100 					+ HtmlUtils.htmlEscape(originalFilename);
101 			if (logger.isDebugEnabled()) {
102 				logger.debug(message, e);
103 			} else {
104 				logger.info(message);
105 			}
106 			errors.reject("file.upload.failed.downstream", new Object[] { originalFilename }, message);
107 		}
108 		
109 		if (errors.hasErrors()) {
110 			list(model, startFile, pageSize);
111 			return "files";			
112 		}
113 
114 		return "redirect:files";
115 
116 	}
117 
118 	@RequestMapping(value = "/files", method = RequestMethod.GET)
119 	public void list(ModelMap model, @RequestParam(defaultValue = "0") int startFile,
120 			@RequestParam(defaultValue = "20") int pageSize) throws Exception {
121 
122 		List<FileInfo> files = fileService.getFiles(startFile, pageSize);
123 		Collections.sort(files);
124 		model.put("files", files);
125 
126 	}
127 
128 	@RequestMapping(value = "/files/**", method = RequestMethod.GET)
129 	public String get(HttpServletRequest request, HttpServletResponse response, ModelMap model,
130 			@RequestParam(defaultValue = "0") int startFile, @RequestParam(defaultValue = "20") int pageSize,
131 			@ModelAttribute("date") Date date, Errors errors) throws Exception {
132 
133 		list(model, startFile, pageSize);
134 
135 		String path = request.getPathInfo().substring("/files/".length());
136 		Resource file = fileService.getResource(path);
137 		if (file == null || !file.exists()) {
138 			errors.reject("file.download.missing", new Object[] { path },
139 					"File download failed for missing file at path=" + HtmlUtils.htmlEscape(path));
140 			return "files";
141 		}
142 
143 		response.setContentType("application/octet-stream");
144 		try {
145 			FileCopyUtils.copy(file.getInputStream(), response.getOutputStream());
146 		}
147 		catch (IOException e) {
148 			errors.reject("file.download.failed", new Object[] { path }, "File download failed for path=" + HtmlUtils.htmlEscape(path));
149 			logger.info("File download failed for path=" + path, e);
150 			return "files";
151 		}
152 
153 		return null;
154 
155 	}
156 
157 	@RequestMapping(value = "/files", method = RequestMethod.DELETE)
158 	public String delete(ModelMap model, @RequestParam(defaultValue = "**") String pattern) throws Exception {
159 
160 		int deletedCount = fileService.delete(pattern);
161 
162 		model.put("files", new ArrayList<String>());
163 		model.put("deletedCount", deletedCount);
164 
165 		return "redirect:files";
166 
167 	}
168 
169 }