ofbiz——上传工具类HttpRequestFileUpload修改优化

78 篇文章 6 订阅
49 篇文章 2 订阅

在使用HttpRequestFileUpload类实现文件上传功能时,发现单用户没有选择上传文件时,执行uploadObject.doUpload(request);方法时会报错,所以进行了优化。

主要添加了一个Map<String, File> fileMap;成员。当用户没有上传文件时,其uploadObject.getFile("file控件name")对于获取的值为null。

当用户上传多个文件,也会解析保存到fileMap中,之前的实现上传多个文件则无法判断上传了几个文件。

org.apache.ofbiz.base.util.HttpRequestFileUpload类

原来的实现代码:

package org.apache.ofbiz.base.util;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

/**
 * HttpRequestFileUpload - Receive a file upload through an HttpServletRequest
 *
 */
public class HttpRequestFileUpload {

    private int BUFFER_SIZE = 4096;
    private int WAIT_INTERVAL = 200; // in milliseconds
    private int MAX_WAITS = 20;
    private int waitCount = 0;
    private String savePath;
    private String filepath;
    private String filename;
    private String contentType;
    private String overrideFilename = null;
    private Map<String, String> fields;

    public String getOverrideFilename() {
        return overrideFilename;
    }

    public void setOverrideFilename(String ofName) {
        overrideFilename = ofName;
    }

    public String getFilename() {
        return filename;
    }

    public String getFilepath() {
        return filepath;
    }

    public void setSavePath(String savePath) {
        this.savePath = savePath;
    }

    public String getContentType() {
        return contentType;
    }

    public String getFieldValue(String fieldName) {
        if (fields == null || fieldName == null)
            return null;
        return fields.get(fieldName);
    }

    private void setFilename(String s) {
        if (s == null)
            return;

        int pos = s.indexOf("filename=\"");

        if (pos != -1) {
            filepath = s.substring(pos + 10, s.length() - 1);
            // Windows browsers include the full path on the client
            // But Linux/Unix and Mac browsers only send the filename
            // test if this is from a Windows browser
            pos = filepath.lastIndexOf("\\");
            if (pos != -1)
                filename = filepath.substring(pos + 1);
            else
                filename = filepath;
        }
    }

    private void setContentType(String s) {
        if (s == null)
            return;

        int pos = s.indexOf(": ");

        if (pos != -1)
            contentType = s.substring(pos + 2, s.length());
    }

    public void doUpload(HttpServletRequest request) throws IOException {
        ServletInputStream in = request.getInputStream();

        String reqLengthString = request.getHeader("content-length");

        System.out.println("expect " + reqLengthString + " bytes.");
        int requestLength = 0;

        try {
            requestLength = Integer.valueOf(reqLengthString).intValue();
        } catch (Exception e2) {
            e2.printStackTrace();
            return;
        }
        byte[] line = new byte[BUFFER_SIZE];

        int i = -1;

        i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
        requestLength -= i;
        if (i < 3)
            return;
        int boundaryLength = i - 2;

        String boundary = new String(line, 0, boundaryLength); // -2 discards the newline character

        System.out.println("boundary=[" + boundary + "] length is " + boundaryLength);
        fields = new HashMap<String, String>();

        while (requestLength > 0/* i != -1*/) {
            String newLine = "";

            if (i > -1) {
                newLine = new String(line, 0, i);
            }
            if (newLine.startsWith("Content-Disposition: form-data; name=\"")) {
                if (newLine.indexOf("filename=\"") != -1) {
                    setFilename(new String(line, 0, i - 2));
                    if (filename == null)
                        return;
                    // this is the file content
                    i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                    requestLength -= i;

                    setContentType(new String(line, 0, i - 2));

                    // blank line
                    i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                    requestLength -= i;
                    newLine = new String(line, 0, i);
                    String filenameToUse = filename;

                    if (overrideFilename != null) {
                        filenameToUse = overrideFilename;
                    }

                    // first line of actual file
                    i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                    requestLength -= i;
                    newLine = new String(line, 0, i);

                    byte[] lastTwoBytes = new byte[2];

                    if (i > 1) {
                        lastTwoBytes[0] = line[i - 2];
                        lastTwoBytes[1] = line[i - 1];
                    }
                    System.out.println("about to create a file:" + (savePath == null ? "" : savePath) + filenameToUse);
                    // before creating the file make sure directory exists
                    File savePathFile = new File(savePath);
                    if (!savePathFile.exists()) {
                        savePathFile.mkdirs();
                    }
                    FileOutputStream fos = new FileOutputStream((savePath == null ? "" : savePath) + filenameToUse);
                    boolean bail = (new String(line, 0, i).startsWith(boundary));
                    boolean oneByteLine = (i == 1); // handle one-byte lines

                    while ((requestLength > 0/* i != -1*/) && !bail) {

                        // write the current buffer, except the last 2 bytes;
                        if (i > 1) {
                            fos.write(line, 0, i - 2);
                        }

                        oneByteLine = (i == 1); // we need to track on-byte lines differently

                        i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                        requestLength -= i;

                        // the problem is the last line of the file content
                        // contains the new line character.

                        // if the line just read was the last line, we're done.
                        // if not, we must write the last 2 bytes of the previous buffer
                        // just assume that a one-byte line isn't the last line

                        if (requestLength < 1) {
                            bail = true;
                        } else if (oneByteLine) {
                            fos.write(lastTwoBytes, 0, 1); // we only saved one byte
                        } else {
                            fos.write(lastTwoBytes, 0, 2);
                        }

                        if (i > 1) {
                            // save the last 2 bytes of the buffer
                            lastTwoBytes[0] = line[i - 2];
                            lastTwoBytes[1] = line[i - 1];
                        } else {
                            lastTwoBytes[0] = line[0]; // only save one byte
                        }
                    }
                    fos.flush();
                    fos.close();
                } else {
                    // this is a field
                    // get the field name
                    int pos = newLine.indexOf("name=\"");
                    String fieldName = newLine.substring(pos + 6, newLine.length() - 3);

                    // blank line
                    i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                    requestLength -= i;
                    i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                    requestLength -= i;
                    newLine = new String(line, 0, i);
                    StringBuilder fieldValue = new StringBuilder(BUFFER_SIZE);

                    while (requestLength > 0/* i != -1*/ && !newLine.startsWith(boundary)) {
                        // The last line of the field
                        // contains the new line character.
                        // So, we need to check if the current line is
                        // the last line.
                        i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                        requestLength -= i;
                        if ((i == boundaryLength + 2 || i == boundaryLength + 4) // + 4 is eof
                            && (new String(line, 0, i).startsWith(boundary)))
                            fieldValue.append(newLine.substring(0, newLine.length() - 2));
                        else
                            fieldValue.append(newLine);
                        newLine = new String(line, 0, i);
                    }
                    fields.put(fieldName, fieldValue.toString());
                }
            }
            i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
            if (i > -1) {
                requestLength -= i;
            }

        } // end while
    }

    // reads a line, waiting if there is nothing available and reqLen > 0
    private int waitingReadLine(ServletInputStream in, byte[] buf, int off, int len, int reqLen) throws IOException {
        int i = -1;

        while (((i = in.readLine(buf, off, len)) == -1) && (reqLen > 0)) {
            System.out.print("waiting");
            if (waitCount > MAX_WAITS) {
                System.out.println("waited " + waitCount + " times, bailing out while still expecting " +
                    reqLen + " bytes.");
                throw new IOException("waited " + waitCount + " times, bailing out while still expecting " +
                        reqLen + " bytes.");
            }
            waitCount++;
            long endMS = new Date().getTime() + WAIT_INTERVAL;

            while (endMS > (new Date().getTime())) {
                try {
                    wait(WAIT_INTERVAL);
                } catch (Exception e3) {
                    System.out.print(".");
                }
            }
            System.out.println((new Date().getTime() - endMS) + " ms");
        }
        return i;
    }
}

修改后实现代码:

package org.apache.ofbiz.base.util;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

/**
 * HttpRequestFileUpload - Receive a file upload through an HttpServletRequest
 *
 */
public class HttpRequestFileUpload {

    private int BUFFER_SIZE = 4096;
    private int WAIT_INTERVAL = 200; // in milliseconds
    private int MAX_WAITS = 20;
    private int waitCount = 0;
    private String savePath;
    private String filepath;
    private String filename;
    private String contentType;
    private String overrideFilename = null;
    private Map<String, String> fields;
	private Map<String, File> fileMap;

    public String getOverrideFilename() {
        return overrideFilename;
    }

    public void setOverrideFilename(String ofName) {
        overrideFilename = ofName;
    }

    public String getFilename() {
        return filename;
    }

    public String getFilepath() {
        return filepath;
    }

    public void setSavePath(String savePath) {
        this.savePath = savePath;
    }

    public String getContentType() {
        return contentType;
    }

    public String getFieldValue(String fieldName) {
        if (fields == null || fieldName == null)
            return null;
        return fields.get(fieldName);
    }
	public File getFile(String fieldName) {
		if (fileMap == null || fieldName == null)
            return null;
        return fileMap.get(fieldName);
    }
    private void setFilename(String s) {
        if (s == null)
            return;

        int pos = s.indexOf("filename=\"");

        if (pos != -1) {
            filepath = s.substring(pos + 10, s.length() - 1);
            // Windows browsers include the full path on the client
            // But Linux/Unix and Mac browsers only send the filename
            // test if this is from a Windows browser
            pos = filepath.lastIndexOf("\\");
            if (pos != -1)
                filename = filepath.substring(pos + 1);
            else
                filename = filepath;
        }
    }

    private void setContentType(String s) {
        if (s == null)
            return;

        int pos = s.indexOf(": ");

        if (pos != -1)
            contentType = s.substring(pos + 2, s.length());
    }

    public void doUpload(HttpServletRequest request) throws IOException {
        ServletInputStream in = request.getInputStream();

        String reqLengthString = request.getHeader("content-length");

        System.out.println("expect " + reqLengthString + " bytes.");
        int requestLength = 0;

        try {
            requestLength = Integer.valueOf(reqLengthString).intValue();
        } catch (Exception e2) {
            e2.printStackTrace();
            return;
        }
        byte[] line = new byte[BUFFER_SIZE];

        int i = -1;

        i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
        requestLength -= i;
        if (i < 3)
            return;
        int boundaryLength = i - 2;

        String boundary = new String(line, 0, boundaryLength); // -2 discards the newline character

        System.out.println("boundary=[" + boundary + "] length is " + boundaryLength);
        fields = new HashMap<String, String>();
		fileMap = new HashMap<String, File>();

        while (requestLength > 0/* i != -1*/) {
            String newLine = "";

            if (i > -1) {
                newLine = new String(line, 0, i);
            }
            if (newLine.startsWith("Content-Disposition: form-data; name=\"")) {
                if (newLine.indexOf("filename=\"") != -1) {
					int pos = newLine.indexOf("name=\"");
					String fieldName = newLine.substring(pos + 6, newLine.indexOf("\"", pos + 6 ));
					setFilename(new String(line, 0, i - 2));
					if("".equals(filename) || filename == null){
						fileMap.put(fieldName, null);
					}
					else{
						// this is the file content
						i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
						requestLength -= i;

						setContentType(new String(line, 0, i - 2));

						// blank line
						i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
						requestLength -= i;
						newLine = new String(line, 0, i);
						String filenameToUse = filename;

						if (overrideFilename != null) {
							filenameToUse = overrideFilename;
						}

						// first line of actual file
						i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
						requestLength -= i;
						newLine = new String(line, 0, i);

						byte[] lastTwoBytes = new byte[2];

						if (i > 1) {
							lastTwoBytes[0] = line[i - 2];
							lastTwoBytes[1] = line[i - 1];
						}
						System.out.println("about to create a file:" + (savePath == null ? "" : savePath) + filenameToUse);
						// before creating the file make sure directory exists
						File savePathFile = new File(savePath);
						if (!savePathFile.exists()) {
							savePathFile.mkdirs();
						}
						FileOutputStream fos = new FileOutputStream((savePath == null ? "" : savePath) + filenameToUse);
						boolean bail = (new String(line, 0, i).startsWith(boundary));
						boolean oneByteLine = (i == 1); // handle one-byte lines

						while ((requestLength > 0/* i != -1*/) && !bail) {

							// write the current buffer, except the last 2 bytes;
							if (i > 1) {
								fos.write(line, 0, i - 2);
							}

							oneByteLine = (i == 1); // we need to track on-byte lines differently

							i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
							requestLength -= i;

							// the problem is the last line of the file content
							// contains the new line character.

							// if the line just read was the last line, we're done.
							// if not, we must write the last 2 bytes of the previous buffer
							// just assume that a one-byte line isn't the last line

							if (requestLength < 1) {
								bail = true;
							} else if (oneByteLine) {
								fos.write(lastTwoBytes, 0, 1); // we only saved one byte
							} else {
								fos.write(lastTwoBytes, 0, 2);
							}

							if (i > 1) {
								// save the last 2 bytes of the buffer
								lastTwoBytes[0] = line[i - 2];
								lastTwoBytes[1] = line[i - 1];
							} else {
								lastTwoBytes[0] = line[0]; // only save one byte
							}
						}
						fos.flush();
						fos.close();
						fileMap.put(fieldName, new File((savePath == null ? "" : savePath) + filenameToUse));
					}
                } else {
                    // this is a field
                    // get the field name
                    int pos = newLine.indexOf("name=\"");
                    String fieldName = newLine.substring(pos + 6, newLine.length() - 3);

                    // blank line
                    i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                    requestLength -= i;
                    i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                    requestLength -= i;
                    newLine = new String(line, 0, i);
                    StringBuilder fieldValue = new StringBuilder(BUFFER_SIZE);

                    while (requestLength > 0/* i != -1*/ && !newLine.startsWith(boundary)) {
                        // The last line of the field
                        // contains the new line character.
                        // So, we need to check if the current line is
                        // the last line.
                        i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
                        requestLength -= i;
                        if ((i == boundaryLength + 2 || i == boundaryLength + 4) // + 4 is eof
                            && (new String(line, 0, i).startsWith(boundary)))
                            fieldValue.append(newLine.substring(0, newLine.length() - 2));
                        else
                            fieldValue.append(newLine);
                        newLine = new String(line, 0, i);
                    }
                    fields.put(fieldName, fieldValue.toString());
                }
            }
            i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
            if (i > -1) {
                requestLength -= i;
            }

        } // end while
    }

    // reads a line, waiting if there is nothing available and reqLen > 0
    private int waitingReadLine(ServletInputStream in, byte[] buf, int off, int len, int reqLen) throws IOException {
        int i = -1;

        while (((i = in.readLine(buf, off, len)) == -1) && (reqLen > 0)) {
            System.out.print("waiting");
            if (waitCount > MAX_WAITS) {
                System.out.println("waited " + waitCount + " times, bailing out while still expecting " +
                    reqLen + " bytes.");
                throw new IOException("waited " + waitCount + " times, bailing out while still expecting " +
                        reqLen + " bytes.");
            }
            waitCount++;
            long endMS = new Date().getTime() + WAIT_INTERVAL;

            while (endMS > (new Date().getTime())) {
                try {
                    wait(WAIT_INTERVAL);
                } catch (Exception e3) {
                    System.out.print(".");
                }
            }
            System.out.println((new Date().getTime() - endMS) + " ms");
        }
        return i;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值