Java tutorial
/* * Copyright 2013 ZXing 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 com.google.zxing.web; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.io.CharStreams; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.WriterException; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import javax.servlet.ServletRequest; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.EnumMap; import java.util.Map; /** * A reimplementation of the * <a href="https://google-developers.appspot.com/chart/infographics/docs/qr_codes"> * Google Chart Server's QR code encoder</a>, which is now deprecated. * * @author Sean Owen */ @WebServlet("/w/chart") public final class ChartServlet extends HttpServlet { private static final int MAX_DIMENSION = 4096; private static final Collection<Charset> SUPPORTED_OUTPUT_ENCODINGS = ImmutableSet.<Charset>builder() .add(StandardCharsets.UTF_8).add(StandardCharsets.ISO_8859_1).add(Charset.forName("Shift_JIS")).build(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { doEncode(request, response, false); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { doEncode(request, response, true); } private static void doEncode(ServletRequest request, HttpServletResponse response, boolean isPost) throws IOException { ChartServletRequestParameters parameters; try { parameters = doParseParameters(request, isPost); } catch (IllegalArgumentException | NullPointerException e) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.toString()); return; } Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class); hints.put(EncodeHintType.MARGIN, parameters.getMargin()); if (!StandardCharsets.ISO_8859_1.equals(parameters.getOutputEncoding())) { // Only set if not QR code default hints.put(EncodeHintType.CHARACTER_SET, parameters.getOutputEncoding().name()); } hints.put(EncodeHintType.ERROR_CORRECTION, parameters.getEcLevel()); BitMatrix matrix; try { matrix = new QRCodeWriter().encode(parameters.getText(), BarcodeFormat.QR_CODE, parameters.getWidth(), parameters.getHeight(), hints); } catch (WriterException we) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, we.toString()); return; } ByteArrayOutputStream pngOut = new ByteArrayOutputStream(); MatrixToImageWriter.writeToStream(matrix, "PNG", pngOut); byte[] pngData = pngOut.toByteArray(); response.setContentType("image/png"); response.setContentLength(pngData.length); response.setHeader("Cache-Control", "public"); response.getOutputStream().write(pngData); } private static ChartServletRequestParameters doParseParameters(ServletRequest request, boolean readBody) throws IOException { Preconditions.checkArgument("qr".equals(request.getParameter("cht")), "Bad type"); String widthXHeight = request.getParameter("chs"); Preconditions.checkNotNull(widthXHeight, "No size"); int xIndex = widthXHeight.indexOf('x'); Preconditions.checkArgument(xIndex >= 0, "Bad size"); int width = Integer.parseInt(widthXHeight.substring(0, xIndex)); int height = Integer.parseInt(widthXHeight.substring(xIndex + 1)); Preconditions.checkArgument(width > 0 && height > 0, "Bad size"); Preconditions.checkArgument(width <= MAX_DIMENSION && height <= MAX_DIMENSION, "Bad size"); String outputEncodingName = request.getParameter("choe"); Charset outputEncoding = StandardCharsets.UTF_8; if (outputEncodingName != null) { outputEncoding = Charset.forName(outputEncodingName); Preconditions.checkArgument(SUPPORTED_OUTPUT_ENCODINGS.contains(outputEncoding), "Bad output encoding"); } ErrorCorrectionLevel ecLevel = ErrorCorrectionLevel.L; int margin = 4; String ldString = request.getParameter("chld"); if (ldString != null) { int pipeIndex = ldString.indexOf('|'); if (pipeIndex < 0) { // Only an EC level ecLevel = ErrorCorrectionLevel.valueOf(ldString); } else { ecLevel = ErrorCorrectionLevel.valueOf(ldString.substring(0, pipeIndex)); margin = Integer.parseInt(ldString.substring(pipeIndex + 1)); Preconditions.checkArgument(margin > 0, "Bad margin"); } } String text; if (readBody) { text = CharStreams.toString(request.getReader()); } else { text = request.getParameter("chl"); } Preconditions.checkArgument(text != null && !text.isEmpty(), "No input"); return new ChartServletRequestParameters(width, height, outputEncoding, ecLevel, margin, text); } }