在做整合之前先将ueditor源码放入项目同时了解一下ueditor的工作机制。

java上传图片到服务器太慢怎么办_OSS

js报错是因为IDE工具自己的验证导致的,请忽略。。。

从ueditor的源码来看呢,入口在jsp下的controller.jsp

由本人亲自debug的情况来看,在第一次进入页面的时候会进入controller.jsp,主要是加载config.json中的配置内容;再次进入controller.jsp是在点击【上传图片】,当然如果将图片复制到富文本框中也是会触发该controller滴!

java上传图片到服务器太慢怎么办_上传图片_02


ActionEnter的整个调用过程如下图:

接下来重点来了,首先创建UeditorUploadImgServlet

public class UeditorUploadImgServlet extends HttpServlet {
 Logger logger = LogManager.getLogger(getClass());
 private static final long serialVersionUID = 5522372203700422672L;
 private String configJsonPath = “”;
 String rootPath = “”;
@Override
public void init() throws ServletException {
	super.init();
	configJsonPath = this.getServletContext().getRealPath("/")+"/static/UEditor/config.json";
	rootPath = this.getServletConfig().getServletContext().getRealPath("/");
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding( "utf-8" );
	response.setHeader("Content-Type" , "text/html");
	ActionEnter actionNew = new ActionEnter( request, rootPath, configJsonPath);
	logger.info(JSONObject.toJSONString(actionNew));
	response.getWriter().write(actionNew.exec());
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
	request.setCharacterEncoding( "utf-8" );
	response.setHeader("Content-Type" , "text/html");
    try { 	
		ActionEnter actionNew = new ActionEnter(request, rootPath, configJsonPath);
		logger.info(JSONObject.toJSONString(actionNew));
		String result = actionNew.exec();
		logger.info(result);
		response.getWriter().write(result);
    } catch (Exception e) {
    	logger.error(e.getMessage());
    }
}


初始化的时候获取项目根路径【rootPath】以及config.json资源文件的位置

doGet方法初始化页面的时候ueditor会进入,取到config.json内容,

doPost方法是在上传文件时触发的,进入post方法后首先是执行new ActionEnter(request, rootPath, configJsonPath);

我们来看下ActionEnter里边具体执行的内容:

public ActionEnter ( HttpServletRequest request, String rootPath, String configJsonPath) {
 this.request = request;
 this.rootPath = rootPath;
 this.actionType = request.getParameter( “action” );
 this.contextPath = request.getContextPath();
 this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, configJsonPath);
 }

这里我们可以看到主要是初始化一些变量。

从soPost方法我们知道接下来执行的是exec()方法;

我们一步一步往下走会发现最后走到了invoke()方法中的switch分支里边,请看下图(3图)

java上传图片到服务器太慢怎么办_上传图片_03


而这里最终调用的是Uploader()方法;

public class Uploader {
 private HttpServletRequest request = null;
 private Map<String, Object> conf = null;
 private String rootPath = null;
public Uploader(HttpServletRequest request, Map<String, Object> conf, String rootPath) {
	this.request = request;
	this.conf = conf;
	this.rootPath = rootPath;
}

public final State doExec() {
	String filedName = (String) this.conf.get("fieldName");
	State state = null;

	if ("true".equals(this.conf.get("isBase64"))) {
		state = Base64Uploader.save(this.request.getParameter(filedName),
				this.conf);
	} else {
		state = BinaryUploader.save(this.request, this.conf, this.rootPath);
	}

	return state;
}


由于我这里不是【isBase64】所以执行的else中的内容,由此我们又到了BinaryUploader的save()方法
关键点来了,

public class BinaryUploader {
 private static Logger logger = LogManager.getLogger(BinaryUploader.class);
public static final State save(HttpServletRequest request, Map<String, Object> conf, String rootPath) {
	FileItemStream fileStream = null;
	boolean isAjaxUpload = request.getHeader("X_Requested_With") != null;

	if (!ServletFileUpload.isMultipartContent(request)) {
		return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
	}

	ServletFileUpload upload = new ServletFileUpload(
			new DiskFileItemFactory());

	if (isAjaxUpload) {
		upload.setHeaderEncoding("UTF-8");
	}

	try {
		FileItemIterator iterator = upload.getItemIterator(request);

		while (iterator.hasNext()) {
			fileStream = iterator.next();

			if (!fileStream.isFormField())
				break;
			fileStream = null;
		}

		if (fileStream == null) {
			return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
		}

		String savePath = (String) conf.get("savePath");// 保存路径【imagePathFormat】
		String originFileName = fileStream.getName(); // 图片流
		String suffix = FileType.getSuffixByFilename(originFileName);// 取到后缀名

		originFileName = originFileName.substring(0,
				originFileName.length() - suffix.length());
		savePath = savePath + suffix;

		long maxSize = ((Long) conf.get("maxSize")).longValue();

		if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
			return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
		}

		savePath = PathFormat.parse(savePath, originFileName);// 保存路径真实生成的路径

		String physicalPath = (String) conf.get("rootPath") + savePath;

		InputStream is = fileStream.openStream();
		// State storageState = StorageManager.saveFileByInputStream(is,
		// physicalPath, maxSize); //此行注释掉
		State storageState = null;

		/**
		 * 上传到阿里云OSS by lichenyi
		 * 
		 */
		// *******************开始***********************
		String fileName = new StringBuffer().append(new Date().getTime()).append(fileStream.getName().substring(fileStream.getName().indexOf("."))).toString();
		try {

			// 创建上传Object的Metadata
			//创建文件
			UploadOSSUtil.createTempFile(rootPath+fileName, is);
			//上传到OSS
			UploadOSSUtil.uploadImgAliyun(new File(rootPath+fileName), fileName);
			//删除文件
			UploadOSSUtil.removeTempFile(rootPath+fileName);
			storageState = StorageManager.saveFileByInputStream(is, physicalPath, maxSize);
			//storageState.putInfo("state", "SUCCESS");// UEDITOR的规则:不为SUCCESS则显示state的内容
			// 注意:下面的url是返回到前端访问文件的路径,请自行修改
			String host = "http://" + ApiUrl.bucket + "." + ApiUrl.endpoint;
			storageState.putInfo("url", host + "/"+ ApiUrl.myPath +"/" + fileName);
			storageState.putInfo("title", fileName);
			storageState.putInfo("original", fileName);
		} catch (Exception e) {
			// TODO: handle exception
			logger.error(e.getMessage());
			storageState.putInfo("state", "文件上传失败!");
			storageState.putInfo("url", "");
			storageState.putInfo("title", "");
			storageState.putInfo("original", "");
			logger.error("文件 " + fileName + " 上传失败!");
		}
		// ********************结束**********************

		is.close();
		if (storageState.isSuccess()) {
			//storageState.putInfo("url", PathFormat.format(savePath));
			storageState.putInfo("type", suffix);
			storageState.putInfo("original", originFileName + suffix);
		}

		return storageState;
	} catch (FileUploadException e) {
		return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
	} catch (IOException e) {
	}
	return new BaseState(false, AppInfo.IO_ERROR);
}

private static boolean validType(String type, String[] allowTypes) {
	List<String> list = Arrays.asList(allowTypes);

	return list.contains(type);
}

public static final String getContentType(String fileName) {
	String fileExtension = fileName.substring(fileName.lastIndexOf("."));
	if ("bmp".equalsIgnoreCase(fileExtension))
		return "image/bmp";
	if ("gif".equalsIgnoreCase(fileExtension))
		return "image/gif";
	if ("jpeg".equalsIgnoreCase(fileExtension)
			|| "jpg".equalsIgnoreCase(fileExtension)
			|| "png".equalsIgnoreCase(fileExtension))
		return "image/jpeg";
	if ("html".equalsIgnoreCase(fileExtension))
		return "text/html";
	if ("txt".equalsIgnoreCase(fileExtension))
		return "text/plain";
	if ("vsd".equalsIgnoreCase(fileExtension))
		return "application/vnd.visio";
	if ("ppt".equalsIgnoreCase(fileExtension)
			|| "pptx".equalsIgnoreCase(fileExtension))
		return "application/vnd.ms-powerpoint";
	if ("doc".equalsIgnoreCase(fileExtension)
			|| "docx".equalsIgnoreCase(fileExtension))
		return "application/msword";
	if ("xml".equalsIgnoreCase(fileExtension))
		return "text/xml";
	return "text/html";
}


看到这里你们可能会有疑问,为什么拿到了输入流,还要再创建临时文件,通过OSS上传呢?
其实呢,通过输入流上传我也试了,可能因为没有找对方法吧,最终还是失败了,(叹气。。。)
下面是UploadOSSUtil类

public class UploadOSSUtil {
 private static Logger logger = LogManager.getLogger(UploadOSSUtil.class);
public UploadOSSUtil() {
}

public static void uploadImgAliyun(File file, String fileName) throws FileNotFoundException {
	String endpoint = ApiUrl.endpoint;
	String accessId = ApiUrl.accessId;
	String accessKey = ApiUrl.accessKey;
	String bucket = ApiUrl.bucket;
	String dir = ApiUrl.myPath+"/";
	OSSClient client = new OSSClient("http://"+endpoint, accessId, accessKey);
	client.putObject(bucket, dir + fileName, file);
	client.shutdown();
}

public static void createTempFile(String path, InputStream inputStream){
	try {
		DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(path));  
        int byteCount = 0;  
        //1M逐个读取  
        byte[] bytes = new byte[1024*1024];  
        while ((byteCount = inputStream.read(bytes)) != -1){  
            outputStream.write(bytes, 0, byteCount);  
        }  
        inputStream.close();
        outputStream.close();
	} catch (FileNotFoundException e) {
		e.printStackTrace();
		logger.error(e.getMessage());
	} catch (IOException e) {
		e.printStackTrace();
		logger.error(e.getMessage());
	}
}

public static void removeTempFile(String path){
	File file = new File(path);
	file.delete();
}


按照以上步骤整合之后,发现返回值是OK的,但是富文本框中就是不现实图片, 最后没办法,用map重新写了一次,细心的童鞋会发现,图3最后一行代码是注释掉的,一下代码紧接该该处

java上传图片到服务器太慢怎么办_OSS_04


代码:https://github.com/lichenyigit/java.ueditorOSS.demo 至此全部整合完毕,有什么问题请留言,感谢不吝赐教

另附上springboot 和 ueditor整合的demo:

https://github.com/lichenyigit/java.springBootUEditorOSS.demo.git