Fckeditor默认是带图片上传的功能 但是这不能满足我们的要求 比如说有的版本的Fckeditor有中文乱码的问题,我用的这个Fckediotr上传图片还有Bug,另外也没办法给图片加水印,传上去的图片还是放在工程下的将来会导致图片越来越庞大,怎么办呢? 我们自己动手丰衣足食,把fckeditor改造成我们需要的.
我用的Fckeditor的jar包是2.5版本的 这个版本图片没有中文乱码 另外如果有中文乱码的问题我建议也不要把图片名称改为UUID名称,因为当用户把自己的图片传上去的时候 想点浏览在去找这张图片的时候 他发现上面的那么多的名字根本分不清哪个是他这次传上来的.有人会问那图片名字重复了怎么办呢?Fckeditor已经考虑到这个问题了 他检测到服务器上有这个名字的图片他会自动重命名.废话不多说了我们来看我是怎么干的.
我们要解决的几个问题
1.上传图片放到服务器的一个物理位置而不是工程下.
2.解决Fckeditor2.5版本中图片上传 没有flush的问题
3.增加水印功能.
Fckeditor低版本的时候我们需要重写一个Servlet 但是我发现这个版本图片上传功能是放在一个类下的而不是
旧版本中的ConnectorServlet.那既然需要重写一个类 而这个类呢有是ConnectorServlet中调用的那我们是不是得先重写ConnectorServlet 然后在重写这个类,然后再把自己写的ConnectorServlet配置到web.xml中呢?不用那么麻烦我不是那样做的 看下图我是怎么做的 ,并请大家自己思考为什么可以这么做.
我在工程下建了和fckeditor相同的包结构然后把我需要重写的类从Fckeditor源代码中拷了过来
好了 我们开始修改吧
Dispatcher.java中doPost方法
UploadResponse doPost(final HttpServletRequest request) {
logger.debug("Entering Dispatcher#doPost");
//String type = null;
Context context = ThreadLocalData.getContext();
context.logBaseParameters();
UploadResponse uploadResponse = null;
// check permissions for user actions
if (!RequestCycleHandler.isEnabledForFileUpload(request))
uploadResponse = UploadResponse.getFileUploadDisabledError();
// check parameters
else if (!Command.isValidForPost(context.getCommandStr()))
uploadResponse = UploadResponse.getInvalidCommandError();
else if (!ResourceType.isValidType(context.getTypeStr()))
uploadResponse = UploadResponse.getInvalidResourceTypeError();
else if (!UtilsFile.isValidPath(context.getCurrentFolderStr()))
uploadResponse = UploadResponse.getInvalidCurrentFolderError();
else {
// call the Connector#fileUpload
ResourceType type = context.getDefaultResourceType();
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> items = upload.parseRequest(request);
// We upload just one file at the same time
FileItem uplFile = items.get(0);
// Some browsers transfer the entire source path not just the
// filename
String fileName = FilenameUtils.getName(uplFile.getName());
logger.debug("Parameter NewFile: {}", fileName);
// check the extension
if (type.isNotAllowedExtension(FilenameUtils
.getExtension(fileName)))
uploadResponse = UploadResponse.getInvalidFileTypeError();
// Secure image check (can't be done if QuickUpload)
else if (type.equals(ResourceType.IMAGE)
&& PropertiesLoader.isSecureImageUploads()
&& !UtilsFile.isImage(uplFile.getInputStream())) {
uploadResponse = UploadResponse.getInvalidFileTypeError();
} else {
String sanitizedFileName = UtilsFile
.sanitizeFileName(fileName);
//修改为UUID文件名称 我这里注释掉了 如下代码可以把上传的图片名称改为UUID
//sanitizedFileName = UUID.randomUUID().toString()+sanitizedFileName.substring(sanitizedFileName.lastIndexOf("."), sanitizedFileName.length());
logger.debug("Parameter NewFile (sanitized): {}",
sanitizedFileName);
String newFileName = connector.fileUpload(type, context
.getCurrentFolderStr(), sanitizedFileName, uplFile
.getInputStream());
String fileUrl = UtilsResponse.fileUrl(RequestCycleHandler
.getUserFilesPath(request), type, context
.getCurrentFolderStr(), newFileName);
//Fckeditor上传有两种 一种是上传图片 一种是上传附件
//如果是图片的话 我用这个action来预览图片
if(type.equals(ResourceType.IMAGE))
{
fileUrl = "tumbnail.action?fileName="+sanitizedFileName;
}
//如果是上传附件的话 用如下的action来下载附件
else if(type.equals(ResourceType.FILE)){
sanitizedFileName = URLEncoder.encode(sanitizedFileName, "utf-8");
fileUrl = request.getContextPath()+"/attachmentDownload.action?fileName="+sanitizedFileName;
}
if (sanitizedFileName.equals(newFileName))
uploadResponse = UploadResponse.getOK(fileUrl);
else {
uploadResponse = UploadResponse.getFileRenamedWarning(fileUrl, newFileName);
logger.debug("Parameter NewFile (renamed): {}",
newFileName);
}
}
uplFile.delete();
} catch (InvalidCurrentFolderException e) {
uploadResponse = UploadResponse.getInvalidCurrentFolderError();
} catch (WriteException e) {
uploadResponse = UploadResponse.getFileUploadWriteError();
} catch (IOException e) {
uploadResponse = UploadResponse.getFileUploadWriteError();
} catch (FileUploadException e) {
uploadResponse = UploadResponse.getFileUploadWriteError();
}
}
logger.debug("Exiting Dispatcher#doPost");
return uploadResponse;
}
AbstractLocalFileSystemConnector.java 中 fileUpload方法
public String fileUpload(final ResourceType type, final String currentFolder, final String fileName, final InputStream inputStream) throws InvalidCurrentFolderException, WriteException {
String absolutePath = getRealUserFilesAbsolutePath(RequestCycleHandler.getUserFilesAbsolutePath(ThreadLocalData.getRequest()));
File typeDir = getOrCreateResourceTypeDir(absolutePath, type);
File currentDir = new File(typeDir, currentFolder);
if (!currentDir.exists() || !currentDir.isDirectory())
throw new InvalidCurrentFolderException();
File newFile = new File(currentDir, fileName);
File fileToSave = UtilsFile.getUniqueFile(newFile.getAbsoluteFile());
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(fileToSave);
IOUtils.copyLarge(inputStream, outputStream);
} catch (IOException e) {
throw new WriteException();
} finally {
try {
if (outputStream != null) {
//这里解决这个版本中图片上传没有flush的bug
outputStream.flush();
IOUtils.closeQuietly(outputStream);
}
IOUtils.closeQuietly(inputStream);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
String format = fileToSave.getName().substring(fileToSave.getName().lastIndexOf(".") + 1, fileToSave.getName().length());
//下面给图片加水印
//如果是图片的话 加水印
if (ImageUtils.isPicture(format)) {
ImageUtils.pressImage(servletContext.getRealPath("themes/cms/image/") +"\\"+ "sxgajj.png", newFile.getAbsoluteFile().getAbsolutePath());
}
return fileToSave.getName();
}
另外还有图片预览的action 和 加水印的代码
图片预览的action代码
public class FckImgPreviewAction {
private String fileName;
public String execute() {
if (fileName != null) {
//图片在服务器上的物理存放路径
String path = ResourceBundle.getBundle("sysConfig").getString("userFilePath.image");
File file = new File("/" + path + fileName);
HttpServletResponse resp = ServletActionContext.getResponse();
OutputStream os = null;
InputStream is = null;
if (file.exists()) {
try {
is = new FileInputStream(file);
os = resp.getOutputStream();
IOUtils.copyLarge(is, os);
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
IOUtils.closeQuietly(is);
if(os != null)
{
os.flush();
IOUtils.closeQuietly(os);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
/**
* @param pressImg 水印文件路径
* @param targetImg 目标文件路径
*/
public final static void pressImage(String pressImg, String targetImg) {
FileOutputStream out = null;
try {
File _file = new File(targetImg);
Image src = ImageIO.read(_file);
int wideth = src.getWidth(null);
int height = src.getHeight(null);
BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.createGraphics();
g.drawImage(src, 0, 0, wideth, height, null);
// 水印文件
File _filebiao = new File(pressImg);
Image src_biao = ImageIO.read(_filebiao);
int wideth_biao = src_biao.getWidth(null);
int height_biao = src_biao.getHeight(null);
g.drawImage(src_biao, wideth - wideth_biao, height - height_biao, wideth_biao, height_biao, null);
// /
g.dispose();
out = new FileOutputStream(targetImg);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(image);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(out!=null)
{
try {
out.flush();
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
还有个重要的类差点忘了 GetResponse.java GetResponse方法
让fck在上传完图片后 fck图片预览图片url正确的显示
public GetResponse(Command command, ResourceType type,
String currentFolder, String constructedUrl) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
Element root = document.createElement("Connector");
document.appendChild(root);
root.setAttribute("command", command.getName());
root.setAttribute("resourceType", type.getName());
Element currentFolderElement = document.createElement("CurrentFolder");
currentFolderElement.setAttribute("path", currentFolder);
if(type.equals(ResourceType.IMAGE))
{
constructedUrl = "tumbnail.action?fileName=";
}
else if(type.equals(ResourceType.FILE)){
constructedUrl = "attachmentDownload.action?fileName=";
}
currentFolderElement.setAttribute("url", constructedUrl);
//System.out.println(constructedUrl);
root.appendChild(currentFolderElement);
}
ok了 看下效果