⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmsrequesthttpservlet.java

📁 cms是开源的框架
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        // The real boundary is always preceeded by an extra "--"
        boundary = "--" + boundary;
        return boundary;
    }

    /**
     * Extracts and returns the content type from a line, or null if the
     * line was empty.
     * @param line Line from input stream.
     * @return Content type of the line.
     * @throws IOException Throws an IOException if the line is malformatted.
     */
    private String extractContentType(String line) throws IOException {
        String contentType = null;

        // Convert the line to a lowercase string
        String origline = line;
        line = origline.toLowerCase();

        // Get the content type, if any
        if (line.startsWith("content-type")) {
            int start = line.indexOf(" ");
            if (start == -1) {
                throw new IOException("Content type corrupt: " + origline);
            }
            contentType = line.substring(start + 1);
        } else {
            if (line.length() != 0) {
                // no content type, so should be empty
                throw new IOException("Malformed line after disposition: " + origline);
            }
        }
        return contentType;
    }

    /**
     * Extracts and returns disposition info from a line, as a String array
     * with elements: disposition, name, filename.  Throws an IOException
     * if the line is malformatted.
     *
     * @param line Line from input stream.
     * @return Array of string containing disposition information.
     * @throws IOException if the line is malformatted
     */
    private String[] extractDispositionInfo(String line) throws IOException {

        // Return the line's data as an array: disposition, name, filename
        String[] retval = new String[3];

        // Convert the line to a lowercase string without the ending \r\n
        // Keep the original line for error messages and for variable names.
        String origline = line;
        line = origline.toLowerCase();

        // Get the content disposition, should be "form-data"
        int start = line.indexOf("content-disposition: ");
        int end = line.indexOf(";");
        if (start == -1 || end == -1) {
            throw new IOException("Content disposition corrupt: " + origline);
        }
        String disposition = line.substring(start + 21, end);
        if (!disposition.equals("form-data")) {
            throw new IOException("Invalid content disposition: " + disposition);
        }

        // Get the field name
        // start at last semicolon
        start = line.indexOf("name=\"", end);

        // skip name=\"
        end = line.indexOf("\"", start + 7);
        if (start == -1 || end == -1) {
            throw new IOException("Content disposition corrupt: " + origline);
        }
        String name = origline.substring(start + 6, end);

        // Get the filename, if given
        String filename = null;

        // start after name
        start = line.indexOf("filename=\"", end + 2);

        // skip filename=\"
        end = line.indexOf("\"", start + 10);

        // note the !=
        if (start != -1 && end != -1) {
            filename = origline.substring(start + 10, end);

            // The filename may contain a full path.  Cut to just the filename.
            int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
            if (slash > -1) {
                filename = filename.substring(slash + 1); // past last slash
            }
            if (filename.equals("")) {
                filename = "unknown"; // sanity check
            }
        }

        // Translate the filename using the resource translator        
        filename = m_translator.translateResource(filename);

        // Return a String array: disposition, name, filename
        retval[0] = disposition;
        retval[1] = name;
        retval[2] = filename;
        return retval;
    }

    /**
     * A utility method that reads a single part of the multipart request
     * that represents a file. Unlike the method name it does NOT saves the file to disk.
     * The name is from the original O'Reilly implmentaton.
     * <p>
     * A subclass can override this method for a better optimized or
     * differently behaved implementation.
     *
     * @param in The stream from which to read the file.
     * @param boundary The boundary signifying the end of this part.
     * @return the output
     * @throws IOException If there's a problem reading or parsing the request.
     */
    private byte[] readAndSaveFile(CmsMultipartInputStreamHandler in, String boundary) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream(8 * 1024);
        byte[] boundaryBytes = boundary.getBytes();
        int[] lookaheadBuf = new int[boundary.length() + 3];
        int[] newLineBuf =  {
            -1, -1
        };
        int matches = 0;
        int matchingByte = new Byte(boundaryBytes[matches]).intValue();

        /*
        File parts of multipart request should not be read line by line.
        Since some servlet environments touch and change the new line
        character(s) when calling the ServletInputStream's <code>readLine</code>
        this may cause problems with binary file uploads.
        We decided to read this parts byte by byte here.
        */
        int read = in.read();
        while (read > -1) {
            if (read == matchingByte) {

                // read byte is matching the next byte of the boundary
                // we should not write to the output stream here.
                lookaheadBuf[matches] = read;
                matches++;
                if (matches == boundary.length()) {

                    // The end of the Boundary has been reached.
                    // Now snip the following line feed.
                    read = in.read();
                    if (newLineBuf[1] == read) {

                        // New line contains ONE single character.
                        // Write the last byte of the buffer to the output stream.
                        out.write(newLineBuf[0]);
                    } else {

                        // new line contains TWO characters, possibly "\r\n"
                        // The bytes in the buffer are not part of the file.
                        // We even have to read one more byte.
                        in.read();
                    }
                    break;
                }
                matchingByte = new Byte(boundaryBytes[matches]).intValue();
            } else {

                // read byte does not match the next byte of the boundary
                // write the first buffer byte to the output stream
                if (newLineBuf[0] != -1) {
                    out.write(newLineBuf[0]);
                }
                if (matches == 0) {

                    // this may be the most propably case.
                    newLineBuf[0] = newLineBuf[1];
                } else {

                    // we have started to read the boundary.
                    // Unfortunately, this was NOT the real boundary.
                    // Fall back to normal read mode.
                    // write the complete buffer to the output stream
                    if (newLineBuf[1] != -1) {
                        out.write(newLineBuf[1]);
                    }
                    for (int i = 0; i < matches; i++) {
                        out.write(lookaheadBuf[i]);
                    }

                    // reset boundary matching counter
                    matches = 0;
                    matchingByte = new Byte(boundaryBytes[matches]).intValue();

                    // clear buffer
                    newLineBuf[0] = -1;
                }

                // put the last byte read into the buffer.
                // it may be part of a line feed.
                newLineBuf[1] = read;
            }
            read = in.read();
        }
        out.flush();
        return out.toByteArray();
    }

    /**
     * A utility method that reads an individual part.  Dispatches to
     * readParameter() and readAndSaveFile() to do the actual work.
     * <p>
     * The single files are stored in a hashtable (seperated in filename and contents)
     * for later addition to a CmsFile Object
     * <p> A subclass can override this method for a better optimized or
     * differently behaved implementation.
     *
     * @param in The stream from which to read the part
     * @param boundary The boundary separating parts
     * @return A flag indicating whether this is the last part
     * @throws IOException If there's a problem reading or parsing the
     * request
     */
    private boolean readNextPart(CmsMultipartInputStreamHandler in, String boundary) throws IOException {

        // Read the first line, should look like this:
        // content-disposition: form-data; name="field1"; filename="file1.txt"
        String line = in.readLine();
        if (line == null || line.equals("")) {

            // No parts left, we're done
            return true;
        }

        // Parse the content-disposition line
        String[] dispInfo = extractDispositionInfo(line);

        // String disposition = dispInfo[0];
        String name = dispInfo[1];
        String filename = dispInfo[2];

        // Now onto the next line.  This will either be empty
        // or contain a Content-Type and then an empty line.
        line = in.readLine();
        if (line == null) {

            // No parts left, we're done
            return true;
        }

        // Get the content type, or null if none specified
        String contentType = extractContentType(line);
        if (contentType != null) {

            // Eat the empty line
            line = in.readLine();
            if (line == null || line.length() > 0) { // line should be empty
                line = in.readLine();
                if (line == null || line.length() > 0) { // line should be empty
                    throw new IOException("Malformed line after content type: " + line);
                }
            }
            
        } else {

            // Assume a default content type
            contentType = "application/octet-stream";
        }

        // Now, finally, we read the content (end after reading the boundary)
        if (filename == null) {

            // This is a parameter
            String value = readParameter(in, boundary);
            m_parameters.put(name, value);
        } else {
            m_filecounter++;
            // stroe the filecontent
            m_files.put(filename, readAndSaveFile(in, boundary));
            // store the name of the file to the parameters
            m_parameters.put(name, filename);
        }

        // there's more to read
        return false;
    }

    /**
     * A utility method that reads a single part of the multipart request
     * that represents a parameter.  A subclass can override this method
     * for a better optimized or differently behaved implementation.
     *
     * @param in The stream from which to read the parameter information
     * @param boundary The boundary signifying the end of this part
     * @return The parameter value
     * @throws IOException If there's a problem reading or parsing the
     * request
     */
    private String readParameter(CmsMultipartInputStreamHandler in, String boundary) throws IOException {
        StringBuffer sbuf = new StringBuffer();
        String line;
        while ((line = in.readLine()) != null) {
            if (line.startsWith(boundary)) {
                break;
            }

            // add the \r\n in case there are many lines
            sbuf.append(line + "\r\n");
        }
        if (sbuf.length() == 0) {

            // nothing read
            return null;
        }

        // cut off the last line's \r\n
        sbuf.setLength(sbuf.length() - 2);

        // no URL decoding needed
        return sbuf.toString();
    }

    /**
     * This method actually parses the request.  A subclass
     * can override this method for a better optimized or differently
     * behaved implementation.
     *
     * @throws IOException If the uploaded content is larger than
     * <tt>maxSize</tt> or there's a problem parsing the request.
     */
    private void readRequest() throws IOException {

        // Check the content type to make sure it's "multipart/form-data"
        String type = m_req.getContentType();
        if (type == null || !type.toLowerCase().startsWith("multipart/form-data")) {
            throw new IOException(C_REQUEST_NOMULTIPART);
        }

        int length = m_req.getContentLength();

        // Get the boundary string; it's included in the content type.
        // Should look something like "------------------------12012133613061"
        String boundary = extractBoundary(type);
        if (boundary == null) {
            throw new IOException(C_REQUEST_NOBOUNDARY);
        }

        // Construct the special input stream we'll read from
        CmsMultipartInputStreamHandler in = new CmsMultipartInputStreamHandler(m_req.getInputStream(), length);

        // Read the first line, should be the first boundary
        String line = in.readLine();
        if (line == null) {
            throw new IOException(C_REQUEST_PROMATUREEND);
        }

        // Verify that the line is the boundary
        if (!line.startsWith(boundary)) {
            throw new IOException(C_REQUEST_NOBOUNDARY);
        }

        // Now that we're just beyond the first boundary, loop over each part
        boolean done = false;
        while (!done) {
            done = readNextPart(in, boundary);
        }

        // Unfortunately some servlet environmets cannot handle multipart
        // requests AND URL parameters at the same time, we have to manage
        // the URL params ourself here. So try to read th URL parameters:
        String queryString = m_req.getQueryString();
        if (queryString != null) {
            StringTokenizer st = new StringTokenizer(m_req.getQueryString(), "&");
            while (st.hasMoreTokens()) {

                // Loop through all parameters
                String currToken = st.nextToken();
                if (currToken != null && !"".equals(currToken)) {

                    // look for the "=" character to divide parameter name and value
                    int idx = currToken.indexOf("=");
                    if (idx > -1) {
                        String key = currToken.substring(0, idx);
                        String value = (idx < (currToken.length() - 1)) ? currToken.substring(idx + 1) : "";
                        m_parameters.put(key, value);
                    }
                }
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -