/* * Copyright 2015-2016 EuregJUG. * * 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 eu.euregjug.site.assets; import com.mongodb.gridfs.GridFSDBFile; import java.io.IOException; import java.io.InputStream; import java.util.Optional; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.tika.Tika; import org.apache.tika.io.TikaInputStream; import org.apache.tika.mime.MediaType; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.gridfs.GridFsTemplate; import org.springframework.security.access.prepost.PreAuthorize; 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.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME; import static org.springframework.web.bind.annotation.RequestMethod.POST; import static java.time.ZoneId.of; import static java.time.ZonedDateTime.now; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import static org.springframework.http.HttpStatus.CREATED; import org.springframework.web.bind.annotation.ResponseStatus; /** * @author Michael J. Simons, 2015-12-29 */ @Controller @RequestMapping("/api/assets") @RequiredArgsConstructor @Slf4j class AssetApiController { private final Tika tika = new Tika(); private final GridFsTemplate gridFs; @RequestMapping(method = POST) @PreAuthorize("isAuthenticated()") @ResponseBody @ResponseStatus(CREATED) public String create( @RequestParam("assetData") final MultipartFile assetData ) throws IOException { // Check duplicates final GridFSDBFile file = this.gridFs.findOne(Query.query(Criteria.where("filename").is(assetData.getOriginalFilename()))); if (file != null) { throw new DataIntegrityViolationException(String.format("Asset with name '%s' already exists", assetData.getOriginalFilename())); } else { try (InputStream usedStream = TikaInputStream.get(assetData.getInputStream())) { MediaType mediaType = null; try { mediaType = MediaType.parse(tika.detect(usedStream, assetData.getOriginalFilename())); } catch (IOException e) { log.warn("Could not detect content type", e); } this.gridFs.store(assetData.getInputStream(), assetData.getOriginalFilename(), Optional.ofNullable(mediaType).map(MediaType::toString).orElse(null)); return assetData.getOriginalFilename(); } } } @RequestMapping({"/{filename:.+}"}) public void get( @PathVariable final String filename, final HttpServletRequest request, final HttpServletResponse response ) throws IOException { final GridFSDBFile file = this.gridFs.findOne(Query.query(Criteria.where("filename").is(filename))); if (file == null) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); } else { final int cacheForDays = 365; response.setHeader("Content-Type", file.getContentType()); response.setHeader("Content-Disposition", String.format("inline; filename=\"%s\"", file.getFilename())); response.setHeader("Expires", now(of("UTC")).plusDays(cacheForDays).format(RFC_1123_DATE_TIME)); response.setHeader("Cache-Control", String.format("max-age=%d, %s", TimeUnit.DAYS.toSeconds(cacheForDays), "public")); file.writeTo(response.getOutputStream()); response.flushBuffer(); } } }