Java tutorial
/* * Copyright (c) 2012-2016, b3log.org & hacpai.com & fangstar.com * * 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.b3log.symphony.processor; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jodd.io.FileUtil; import jodd.upload.MultipartRequestInputStream; import jodd.util.Base64; import jodd.util.MimeTypes; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.b3log.latke.Latkes; import org.b3log.latke.ioc.LatkeBeanManager; import org.b3log.latke.ioc.Lifecycle; import org.b3log.latke.logging.Level; import org.b3log.latke.logging.Logger; import org.b3log.latke.service.ServiceException; import org.b3log.latke.util.MD5; import org.b3log.symphony.SymphonyServletListener; import org.b3log.symphony.model.Option; import org.b3log.symphony.service.OptionQueryService; import org.b3log.symphony.service.UserMgmtService; import org.b3log.symphony.service.UserQueryService; import org.b3log.symphony.util.Symphonys; import org.json.JSONObject; /** * File upload. * * @author <a href="http://88250.b3log.org">Liang Ding</a> * @since 1.4.0 */ @WebServlet(urlPatterns = { "/upload", "/upload/*" }, loadOnStartup = 2) public class FileUploadServlet extends HttpServlet { /** * Serial version UID. */ private static final long serialVersionUID = 1L; /** * Logger. */ private static final Logger LOGGER = Logger.getLogger(FileUploadServlet.class); /** * Upload directory. */ private static final String UPLOAD_DIR = Symphonys.get("upload.dir"); static { if (!FileUtil.isExistingFolder(new File(UPLOAD_DIR))) { try { FileUtil.mkdirs(UPLOAD_DIR); } catch (IOException ex) { LOGGER.log(Level.ERROR, "Init upload dir error", ex); } } } /** * Qiniu enabled. */ private static final Boolean QN_ENABLED = Symphonys.getBoolean("qiniu.enabled"); @Override public void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { if (QN_ENABLED) { return; } final LatkeBeanManager beanManager = Lifecycle.getBeanManager(); final UserQueryService userQueryService = beanManager.getReference(UserQueryService.class); final UserMgmtService userMgmtService = beanManager.getReference(UserMgmtService.class); final OptionQueryService optionQueryService = beanManager.getReference(OptionQueryService.class); try { final JSONObject option = optionQueryService.getOption(Option.ID_C_MISC_ALLOW_ANONYMOUS_VIEW); if (!"0".equals(option.optString(Option.OPTION_VALUE))) { if (null == userQueryService.getCurrentUser(req) && !userMgmtService.tryLogInWithCookie(req, resp)) { final String referer = req.getHeader("Referer"); if (!StringUtils.contains(referer, "fangstar.net")) { final String authorization = req.getHeader("Authorization"); LOGGER.debug("Referer [" + referer + "], Authorization [" + authorization + "]"); if (!StringUtils.contains(authorization, "Basic ")) { resp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } else { String usernamePwd = StringUtils.substringAfter(authorization, "Basic "); usernamePwd = Base64.decodeToString(usernamePwd); final String username = usernamePwd.split(":")[0]; final String password = usernamePwd.split(":")[1]; if (!StringUtils.equals(username, Symphonys.get("http.basic.auth.username")) || !StringUtils.equals(password, Symphonys.get("http.basic.auth.password"))) { resp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } } } } } } catch (final Exception e) { LOGGER.log(Level.ERROR, "Gets file failed", e); resp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } final String uri = req.getRequestURI(); String key = uri.substring("/upload/".length()); key = StringUtils.substringBeforeLast(key, "-64.jpg"); // Erase Qiniu template key = StringUtils.substringBeforeLast(key, "-260.jpg"); // Erase Qiniu template String path = UPLOAD_DIR + key; if (!FileUtil.isExistingFile(new File(path))) { resp.sendError(HttpServletResponse.SC_NOT_FOUND); return; } final byte[] data = IOUtils.toByteArray(new FileInputStream(path)); final String ifNoneMatch = req.getHeader("If-None-Match"); final String etag = "\"" + MD5.hash(new String(data)) + "\""; resp.addHeader("Cache-Control", "public, max-age=31536000"); resp.addHeader("ETag", etag); resp.setHeader("Server", "Latke Static Server (v" + SymphonyServletListener.VERSION + ")"); if (etag.equals(ifNoneMatch)) { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return; } final OutputStream output = resp.getOutputStream(); IOUtils.write(data, output); output.flush(); IOUtils.closeQuietly(output); } @Override public void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { if (QN_ENABLED) { return; } final LatkeBeanManager beanManager = Lifecycle.getBeanManager(); final UserQueryService userQueryService = beanManager.getReference(UserQueryService.class); final UserMgmtService userMgmtService = beanManager.getReference(UserMgmtService.class); try { if (null == userQueryService.getCurrentUser(req) && !userMgmtService.tryLogInWithCookie(req, resp)) { resp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } } catch (final ServiceException e) { LOGGER.log(Level.ERROR, "Gets file failed", e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } final MultipartRequestInputStream multipartRequestInputStream = new MultipartRequestInputStream( req.getInputStream()); multipartRequestInputStream.readBoundary(); multipartRequestInputStream.readDataHeader("UTF-8"); final String mimeType = multipartRequestInputStream.getLastHeader().getContentType(); String suffix; String[] exts = MimeTypes.findExtensionsByMimeTypes(mimeType, false); if (null == exts || 0 == exts.length || exts.length > 1) { suffix = StringUtils.substringAfterLast(multipartRequestInputStream.getLastHeader().getFileName(), "."); } else { suffix = exts[0]; } final String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + suffix; final OutputStream output = new FileOutputStream(UPLOAD_DIR + fileName); IOUtils.copy(multipartRequestInputStream, output); IOUtils.closeQuietly(multipartRequestInputStream); IOUtils.closeQuietly(output); final JSONObject data = new JSONObject(); data.put("key", Latkes.getServePath() + "/upload/" + fileName); resp.setContentType("application/json"); final PrintWriter writer = resp.getWriter(); writer.append(data.toString()); writer.flush(); writer.close(); } }