?? multipartrequest.java
字號:
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 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); parameters.put(name, value); } else { // This is a file readAndSaveFile(in, boundary, filename); if (filename.equals("unknown")) { files.put(name, new UploadedFile(null, null, null)); } else { files.put(name, new UploadedFile(dir.toString(), filename, contentType)); } } return false; // there's more to read } /** * 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 * @exception IOException if there's a problem reading or parsing the * request */ protected String readParameter(MultipartInputStreamHandler in, String boundary) throws IOException { StringBuffer sbuf = new StringBuffer(); String line; while ((line = in.readLine()) != null) { if (line.startsWith(boundary)) break; sbuf.append(line + "\r\n"); // add the \r\n in case there are many lines } if (sbuf.length() == 0) { return null; // nothing read } sbuf.setLength(sbuf.length() - 2); // cut off the last line's \r\n return sbuf.toString(); // no URL decoding needed } /** * A utility method that reads a single part of the multipart request * that represents a file, and saves the file to the given directory. * 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 * @param dir the directory in which to save the uploaded file * @param filename the name under which to save the uploaded file * @exception IOException if there's a problem reading or parsing the * request */ protected void readAndSaveFile(MultipartInputStreamHandler in, String boundary, String filename) throws IOException { File f = new File(dir + File.separator + filename); FileOutputStream fos = new FileOutputStream(f); BufferedOutputStream out = new BufferedOutputStream(fos, 8 * 1024); // 8K byte[] bbuf = new byte[100 * 1024]; // 100K int result; String line; // ServletInputStream.readLine() has the annoying habit of // adding a \r\n to the end of the last line. // Since we want a byte-for-byte transfer, we have to cut those chars. boolean rnflag = false; while ((result = in.readLine(bbuf, 0, bbuf.length)) != -1) { // Check for boundary if (result > 2 && bbuf[0] == '-' && bbuf[1] == '-') { // quick pre-check line = new String(bbuf, 0, result, "ISO-8859-1"); if (line.startsWith(boundary)) break; } // Are we supposed to write \r\n for the last iteration? if (rnflag) { out.write('\r'); out.write('\n'); rnflag = false; } // Write the buffer, postpone any ending \r\n if (result >= 2 && bbuf[result - 2] == '\r' && bbuf[result - 1] == '\n') { out.write(bbuf, 0, result - 2); // skip the last 2 chars rnflag = true; // make a note to write them on the next iteration } else { out.write(bbuf, 0, result); } } out.flush(); out.close(); fos.close(); } // Extracts and returns the boundary token from a line. // private String extractBoundary(String line) { int index = line.indexOf("boundary="); if (index == -1) { return null; } String boundary = line.substring(index + 9); // 9 for "boundary=" // The real boundary is always preceeded by an extra "--" boundary = "--" + boundary; return boundary; } // 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. // 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 = line.indexOf("name=\"", end); // start at last semicolon end = line.indexOf("\"", start + 7); // skip name=\" 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 = line.indexOf("filename=\"", end + 2); // start after name end = line.indexOf("\"", start + 10); // skip filename=\" if (start != -1 && end != -1) { // note the != 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 } // Return a String array: disposition, name, filename retval[0] = disposition; retval[1] = name; retval[2] = filename; return retval; } // Extracts and returns the content type from a line, or null if the // line was empty. 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; }}// A class to hold information about an uploaded file.//class UploadedFile { private String dir; private String filename; private String type; UploadedFile(String dir, String filename, String type) { this.dir = dir; this.filename = filename; this.type = type; } public String getContentType() { return type; } public String getFilesystemName() { return filename; } public File getFile() { if (dir == null || filename == null) { return null; } else { return new File(dir + File.separator + filename); } }}// A class to aid in reading multipart/form-data from a ServletInputStream.// It keeps track of how many bytes have been read and detects when the// Content-Length limit has been reached. This is necessary since some // servlet engines are slow to notice the end of stream.//// Mac users: The Mac doesn't like class names which exceed 32 characters// (including the ".class") so while this class is usable from a JAR // anywhere, it won't compile on a Mac.//class MultipartInputStreamHandler { ServletInputStream in; int totalExpected; int totalRead = 0; byte[] buf = new byte[8 * 1024]; public MultipartInputStreamHandler(ServletInputStream in, int totalExpected) { this.in = in; this.totalExpected = totalExpected; } // Reads the next line of input. Returns null to indicate the end // of stream. // public String readLine() throws IOException { StringBuffer sbuf = new StringBuffer(); int result; String line; do { result = this.readLine(buf, 0, buf.length); // this.readLine() does += if (result != -1) { sbuf.append(new String(buf, 0, result, "ISO-8859-1")); } } while (result == buf.length); // loop only if the buffer was filled if (sbuf.length() == 0) { return null; // nothing read, must be at the end of stream } sbuf.setLength(sbuf.length() - 2); // cut off the trailing \r\n return sbuf.toString(); } // A pass-through to ServletInputStream.readLine() that keeps track // of how many bytes have been read and stops reading when the // Content-Length limit has been reached. // public int readLine(byte b[], int off, int len) throws IOException { if (totalRead >= totalExpected) { return -1; } else { int result = in.readLine(b, off, len); if (result > 0) { totalRead += result; } return result; } }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -