GridFS文件操作
1、BuguFS类
BuguMongo通过BuguFS类来操作GridFS文件系统,能够实现对文件的保存、获取、删除、重命名、移动等操作,而且能够按文件夹组织文件。
BuguFS提供了如下操作:
保存
public void save(File file)
public void save(File file, String filename)
public void save(File file, String filename, String folderName)
public void save(File file, String filename, String folderName, Map<String, Object> params)
public void save(InputStream is, String filename)
public void save(InputStream is, String filename, String folderName)
public void save(InputStream is, String filename, String folderName, Map<String, Object> params)
public void save(byte[] data, String filename)
public void save(byte[] data, String filename, String folderName)
public void save(byte[] data, String filename, String folderName, Map<String, Object> params)
获取一个文件
public GridFSDBFile findOne(String filename)
public GridFSDBFile findOne(DBObject query)
获取文件列表
public List<GridFSDBFile> find(DBObject query)
public List<GridFSDBFile> find(DBObject query, int pageNum, int pageSize)
public List<GridFSDBFile> find(DBObject query, String orderBy)
public List<GridFSDBFile> find(DBObject query, DBObject orderBy)
public List<GridFSDBFile> find(DBObject query, String orderBy, int pageNum, int pageSize)
public List<GridFSDBFile> find(DBObject query, DBObject orderBy, int pageNum, int pageSize)
获取某个文件夹中的文件列表
public List<GridFSDBFile> findByFolder(String folderName)
public List<GridFSDBFile> findByFolder(String folderName, int pageNum, int pageSize)
public List<GridFSDBFile> findByFolder(String folderName, DBObject orderBy)
public List<GridFSDBFile> findByFolder(String folderName, String orderBy)
public List<GridFSDBFile> findByFolder(String folderName, String orderBy, int pageNum, int pageSize)
public List<GridFSDBFile> findByFolder(String folderName, DBObject orderBy, int pageNum, int pageSize)
获取所有的文件夹
public List findAllFolder()
文件重命名
public void rename(String oldName, String newName)
public void rename(GridFSDBFile file, String newName)
文件夹重命名
public void renameFolder(String oldName, String newName)
移动文件
public void move(String filename, String folderName)
public void move(GridFSDBFile file, String folderName)
删除文件
public void remove(String filename)
public void remove(DBObject query)
删除文件夹
public void removeFolder(String folderName) //会同时删除里面的所有文件
与BuguDao中的方法类似,上面的find方法支持使用形如"level:1"、"level:1,price:-1"这样的字符串进行排序。
此外,BuguFS中还有几个常用的静态常量:
public final static String FOLDER = "folder"; //文件夹 public final static String FILENAME = "filename"; //文件名 public final static String LENGTH = "length"; //文件大小,以byte为单位 public final static String UPLOADDATE = "uploadDate"; //上传时间
对于GridFS中每一个文件(GridFSDBFile),都会有filename、length、uploadDate这三个属性。如果保存的时候还设置了文件夹,那么还会有folder属性。
一个代码例子如下:
import com.bugull.mongo.fs.BuguFS;
BuguFS fs = BuguFS.getInstance();
//保存 File file = ...
fs.save(file); //filename使用file.getName()
String filename = ... //提供一个文件名
fs.save(file, filename);
Byte[] data = ... String filename = ...
fs.save(data, filename);
String folderName = "文件夹A"; Map params = new HashMap(); params.put("author", "张三"); params.put("group", "技术");
fs.save(data, filename, folderName, params);
//获取 GridFSDBFile dbFile = fs.findOne(filename); InputStream is = dbFile.getInputStream();
DBObject query = ... List<GridFSDBFile> list = fs.find(query);
String orderBy = BuguFS.UPLOADDATE + ":-1"; List<GridFSDBFile> listOfFolder = fs.findByFolder("文件夹A", orderBy); //取出文件夹A中的文件,并按上传时间倒序排列
//删除
fs.remove(filename);
fs.remove(query);
除了BuguFS外,BuguMongo还提供了另外4个辅助类,来简化GridFS文件的上传和获取,而且功能更加强大。这4个类分别是:
上传:Uploader、ImageUploader、Watermark。
读取:UploadedFileServlet
2、辅助类:文件上传类Uploader
Uploader类有以下几个构造函数:
public Uploader(File file, String originalName) //默认rename=false
public Uploader(File file, String originalName, boolean rename)
public Uploader(InputStream input, String originalName)
public Uploader(InputStream input, String originalName, boolean rename)
public Uploader(byte[] data, String originalName)
public Uploader(byte[] data, String originalName, boolean rename)
上面这些构造函数,如果rename=false,则以提供的originalName作为文件名来保存文件。如果rename=true,则会对文件进行重命名,由系统生成一个形如“2011070799999999999999.doc”的文件名,其中,20110707为日期,9999999999999为当前时间的毫秒数(long值)。
这里,以一个简单的新闻系统为例。
发布一篇新闻的时候,同时上传新闻的附件(比如.doc文件),那么,在Struts2的Action中,代码这样写:
import com.bugull.mongo.fs.Uploader; ... public class CreateNewsAction extends ActionSupport{
private File file;
private String fileFileName;
private News news;
private NewsDao newsDao;
public String execute(){
Uploader uploader = new Uploader(file, fileFileName, true);
uploader.save();
news.setAttachment(uploader.getFilename());
newsDao.save(news);
return SUCCESS;
}
... }
上面的代码中,因为rename=true,因此,uploader.getFilename(),返回的是,文件经过保存以后,系统自动生成的文件名(含扩展名),格式如:2011070799999999999999.doc,其中,20110707为日期,9999999999999为当前时间的毫秒数。news实体中attachment值,就是这个字符串。
如果是使用SpringMVC,那么Controller的代码示例如下:
@Controller public class FileUploadController {
@RequestMapping(value="/upload", method=RequestMethod.POST)
public String handleUpload(@RequestParam("file") MultipartFile file) throws IOException{
InputStream is = file.getInputStream();
String originalName = file.getOriginalFilename();
Uploader uploader = new Uploader(is, originalName, true);
uploader.save();
...
}
}
如果需要把文件上传到指定的文件夹中,Uploader可以这样定义:
String folderName = "文件夹A"; Uploader uploader = new Uploader(file, originalName); //不重命名,使用原文件名
uploader.setFolder(folderName);
uploader.save();
还可以为上传的文件设置其它属性。例如,设置文件的作者:
Uploader uploader = new Uploader(file, fileFileName, true);
uploader.setAttribute("author", "Frank");
uploader.save();
3、图片文件的上传ImageUploader
图片上传使用类ImageUploader,它继承自Uploader,除了具备上面讲的Uploader的功能以外,ImageUploader还能实现图片加水印、图片压缩。
3.1、图片加水印
图片上传的时候,可以自动给图片加上水印。可以是图片水印,也可以是文字水印。
上传图片的时候,给其加上图片水印的代码如下:
import com.bugull.mongo.fs.Watermark; import com.bugull.mongo.fs.ImageUploader; ... public class CreateProductAction extends ActionSupport{
private File img;
private String imgFileName;
private Product product;
private ProductDao productDao;
public String execute(){
Watermark watermark = new Watermark();
watermark.setImagePath("/root/website/images/watermark.png");
ImageUploader uploader = new ImageUploader(img, imgFileName, true);
uploader.save(watermark);
product.setPicture(uploader.getFilename());
productDao.save(product);
return SUCCESS;
}
... }
watermark.setImagePath(imagePath)设置水印文件的路径,该路径是操作系统的绝对路径。
还可以给图片加上文字水印,代码示例如下:
ImageUploader uploader = new ImageUploader(file, fileFileName, true); Watermark watermark = new Watermark();
watermark.setText("www.mongodb.com");
uploader.save(watermark);
Watermark类还有许多其它参数,它们的定义和初始值如下,这些属性值都可以通过watermark.setXXX()来进行设置:
public final static int CENTER = 1; public final static int BOTTOM_RIGHT = 2;
private String imagePath; private String text;
private String fontName = "宋体"; private int fontStyle = Font.PLAIN; private Color color = Color.GRAY; private int fontSize = 30; private float alpha = 0.5f; private int align = CENTER; private int right = 20; private int bottom = 20;
3.2、图片压缩
图片上传的时候,经常还需要将该图片压缩、保存成若干份,代码例子如下:
import com.bugull.mongo.fs.ImageUploader; ... public class CreateProductAction extends ActionSupport{
private File img;
private String imgFileName;
private Product product;
private ProductDao productDao;
public String execute(){
ImageUploader uploader = new ImageUploader(img, imgFileName, true);
uploader.save();
uploader.compress("medium", 300, 300);
uploader.compress("small", 100, 100);
product.setPicture(uploader.getFilename());
productDao.save(product);
return SUCCESS;
}
... }
public void compress(String dimension, int maxWidth, int maxHeight) 方法中,dimension是指图片尺寸的类型,用来区分同一图片的不同尺寸的拷贝。经过compress方法压缩保存后的图片文件,和原图有相同的filename,例如,同样是2011070799999999999999.jpg。
3.3、获取图片尺寸
通过ImageUploader上传的图片,经过保存后,还可以取得图片的宽度和高度,代码示例如下:
ImageUploader uploader = new ImageUploader(file, fileFileName, true);
uploader.save(); int[] size = uploader.getSize(); int width = size[0]; //宽度 int height = size[1]; //高度
4、辅助类:文件获取类UploadedFileServlet
如果你是在Web项目中使用BuguMongo,那么,保存到GridFS中的文件,可以通过UploadedFileServlet来获取,在web.xml中配置如下:
<servlet>
<servlet-name>UploadedFile</servlet-name>
<servlet-class>com.bugull.mongo.fs.UploadedFileServlet</servlet-class> </servlet> <servlet-mapping>
<servlet-name>UploadedFile</servlet-name>
<url-pattern>/UploadedFile/*</url-pattern> </servlet-mapping>
然后,可以通过如下的URL链接来获取文件:
http://www.domain.com/UploadedFile/xxxx.jpg 或者:
http://www.domain.com/UploadedFile/key/value/xxxx.jpg
http://www.domain.com/UploadedFile/key1/value1/key2/value2/xxxx.jpg
其中:
xxxx.jpg——表示文件名,必须提供。
key、value——表示属性名称、属性值。
例如:
http://www.domain.com/UploadedFile/dimension/small/2011070799999999999999.jpg
http://www.domain.com/UploadedFile/author/Frank/dimension/small/2011070799999999999999.jpg
需要特别注意的是,经过ImageUploader.compress()压缩后的图片,默认有一个尺寸属性,属性名称是"dimension",属性值就是compress()函数中的参数值。
对于"jpg", "jpeg", "png", "gif", "bmp", "html", "htm", "swf", "mp3", "mp4", "pdf"等这些能直接在浏览器中使用的文件,通过该Servlet获取,浏览器能对它进行缓存。
对其它类型的文件,返回application/octet-stream格式的内容,浏览器不对它进行缓存。