First, let's review the basics of the InputStream read method,
Within the Java InputStream Read method, there is a postion, which flags the current stream read to the location, each time it is read, the position is moved once, if read to the last, The Inputstream.read method returns 1, the flag has been read, and if you want to read again, you can call the Inputstream.reset method, and position will move to the location where Mark was last called, and Mark defaults to 0, so you can read it from the beginning.
Of course, the ability to reset is conditional, depending on whether the marksupported,marksupported () method returns can be Mark/reset
We'll look back at Request.getinputstream.
The value returned by Request.getinputstream is servletinputstream, viewing servletinputstream source discovery, without rewriting the Reset method, So view InputStream source found marksupported returns false, and the Reset method throws an exception directly.
Inputstream.java
public boolean marksupported () { return false; synchronized void Reset () throws IOException { throw new I Oexception ("Mark/reset not supported"); }
In summary , after the Request.getinputstream read once position to the end of the file, the second time will not read the data, due to reset (), so, Request.getinputstream can only be read once.
Summarize:
The most fundamental problem is the deep understanding of the Read and reset methods of Java IO, especially the internal implementation principle of the Read method.
Attached Servletinputstream.java source code
/* * Licensed to the Apache software Foundation (ASF) under one or more * Contributor license agreements. See the NOTICE file distributed with * This work for additional information regarding copyright ownership. * The ASF licenses this file to you under the Apache License, Version 2.0 * (the "License"); You are not a use of this file except in compliance with * the License. Obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * unless required by applicable Law or agreed into writing, software * Distributed under the License is distributed on a "as is" BASIS, * without Warra Nties or CONDITIONS of any KIND, either express OR implied. * See the License for the specific language governing permissions and * limitations under the License. */package Javax.servlet; Import Java.io.ioexception;import Java.io.InputStream; /** * provides an input stream for reading binary data from a client request, * including an efficient <code>readlin E</code> metHod for reading data one line * at a time. With some protocols, such as HTTP POST and PUT, A * <code>ServletInputStream</code> object can is used to read Data sent from the * client. * <p> * A <code>ServletInputStream</code> object is normally retrieved via the * {@link servletrequest#g Etinputstream} method. * <p> * This was an abstract class A servlet container implements. Subclasses of * This class must implement the <code>java.io.inputstream.read () </code> method. * * @see servletrequest */public abstract class ServletInputStream extends InputStream {/** * Does nothing, because t He is an abstract class. */protected ServletInputStream () {//NOOP}/** * Reads the input stream, one line at a time. Starting at an offset, reads * bytes to an array, until it reads a certain number of bytes or reaches * a newline ch Aracter, which it reads into the array as well. * <p> * This method returns-1 if it reachEs the end of the input stream before * reading the maximum number of bytes. * * @param b * An array of bytes to which data is read * @param off * An integer specifying the Charac ter at which this method * begins reading * @param len * An integer specifying the maximum number of bytes To read * @return A integer specifying the actual number of bytes read, or-1 if * The end of the stream is REAC hed * @exception IOException * If an input or output exception have occurred */public int readLine (byte[] B, int off, int len) throws IOException {if (len <= 0) {return 0; } int count = 0, C; while ((c = Read ())! =-1) {b[off++] = (byte) c; count++; if (c = = ' \ n ' | | count = = len) {break; }} return count > 0? Count:-1; }/** * Returns <code>true</code> If all the data have been read from the stream, * else <code>fals E</code>. * * @since Servlet 3.1 */Public abstract Boolean isfinished (); /** * Returns <code>true</code> If data can be read without blocking, else * <code>false</code> ;. If This method is called and returns FALSE, the * container would invoke {@link readlistener#ondataavailable ()} when data is * available. * * @since Servlet 3.1 */Public abstract Boolean isReady (); /** * Sets the {@link Readlistener} for this {@link servletinputstream} and * thereby switches to non-blocking IO. It is only valid to switch to * non-blocking IO within async processing or HTTP upgrade processing. * * @param listener the non-blocking IO Read listener * * @throws IllegalStateException If this method is called if Neither * Async nor HTTP upgrade is in progress or * if the {@link Readlistener} have Already * been set * @throws nullpointerexception IF listener is null * * @since Servlet 3.1 * /Public AbstraCT void Setreadlistener (Readlistener listener);
This article on the Request.getinputstream can only read once the problem is small part of the whole content to share to everyone, I hope to give you a reference.
The reason that a stream in HttpServletRequest can only be read once