package me.test.first.spring.rs.controller;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import me.test.first.spring.rs.exception.BusinessException;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
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.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UrlPathHelper;
/**
* <table border=1 cellspacing=0 cellpadding=0 >
* <tr>
* <th>URL</th>
* <th>HTTP方法</th>
* <th>作用</th>
* </tr>
* <tr>
* <td>/file</td>
* <td>POST</td>
* <td>上传新文件</td>
* </tr>
* <tr>
* <td>/file/{id}</td>
* <td>HEAD</td>
* <td>检查资源是否可用</td>
* </tr>
* <tr>
* <td>/file/{id}</td>
* <td>GET</td>
* <td>查询指定ID的文件内容</td>
* </tr>
* <tr>
* <td>/file/{id}</td>
* <td>DELETE</td>
* <td>删除指定ID的文件信息</td>
* </tr>
* </table>
*
*/
@Controller
@RequestMapping("/file")
public class FileController {
private final Map<Long, ByteArrayResource> fileMap = new LinkedHashMap<Long, ByteArrayResource>();
@Autowired
private ApplicationContext appCtx;
@Autowired
private UrlPathHelper urlPathHelper = null;
@PostConstruct
public void init() {
try {
byte[] avatar = IOUtils.toByteArray(appCtx.getResource("classpath:avatar.png").getInputStream());
fileMap.put(1L, new ByteArrayResource(avatar, "image/png"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// Should not handle multi file, even should be only one file item in post data.
@RequestMapping(method = RequestMethod.POST)
public void post(@RequestParam("file") MultipartFile file, HttpServletRequest req, HttpServletResponse resp) {
if (file == null) {
throw new BusinessException(HttpStatus.BAD_REQUEST.value(),
"for uploading, parameter name must be \"file\"");
}
if (file.isEmpty()) {
throw new BusinessException(HttpStatus.BAD_REQUEST.value(),
"File could not be empty");
}
ByteArrayResource rsc = null;
try {
rsc = new ByteArrayResource(file.getBytes(),
file.getContentType());
} catch (IOException e) {
throw new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.value(),
"Could not read the file uploaded.");
}
Long maxId = 0L;
for (Long id : fileMap.keySet()) {
if (id > maxId) {
maxId = id;
}
}
Long newId = maxId + 1;
fileMap.put(newId, rsc);
String uri = UriComponentsBuilder.newInstance().path("{contextPath}{servletPath}/file/{id}")
.build()
.expand(urlPathHelper.getContextPath(req),
urlPathHelper.getServletPath(req),
newId)
.encode()
.toUriString();
resp.setHeader("Location", uri);
resp.setStatus(HttpStatus.CREATED.value());
}
@RequestMapping(value = "/{id}", method = RequestMethod.HEAD)
public void head(@PathVariable("id") String idStr, HttpServletResponse resp) {
Long id = null;
try {
id = Long.valueOf(idStr);
} catch (NumberFormatException e) {
throw new BusinessException(HttpStatus.NOT_FOUND.value(),
"file with id =" + id + " not exists");
}
if (!fileMap.containsKey(id)) {
throw new BusinessException(HttpStatus.NOT_FOUND.value(),
"file with id \"" + id + "\" not found.");
}
resp.setStatus(HttpStatus.NO_CONTENT.value());
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
public ByteArrayResource get(@PathVariable("id") String idStr, HttpServletResponse resp) {
head(idStr, resp);
Long id = Long.valueOf(idStr);
resp.setStatus(HttpStatus.OK.value());
ByteArrayResource rsc = fileMap.get(id);
String desp = rsc.getDescription();
if (desp != null && desp.trim().length() != 0) {
resp.setContentType(desp.trim());
}
return rsc;
}
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public void delete(@PathVariable("id") String idStr, HttpServletResponse resp) {
head(idStr, resp);
Long id = Long.valueOf(idStr);
fileMap.remove(id);
resp.setStatus(HttpStatus.NO_CONTENT.value());
}
}