mongodb存储图片和文件实践

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介:

可能很多人会问为何要用mongodb存储图片和文件,我的理由是mongodb作存储方便稳定易扩展,我们自己写的文件存储服务器肯定很LOW,除了含有巨量图片的大型系统,一般由公司自研图片存储外,大部分情况下,我们用mongodb足以应付。另外,很多人根本就不知道或者没尝试过用mongodb存储文件,而对方还故意问我为什么用这个。本文特此奉上代码并提供MongoDBClient与spring的集成。

工程结构代码 收藏代码

whatsmars-common  
  |-src  
    |-main  
      |-java  
        |-com.itlong.whatsmars.common.mongo  
          |-object  
            MongoDBConfig.java  
            MongoDBCredential.java  
            MongoDBDriver.java  
            ObjectIdCreator.java  
          |-serializer  
            CustomDateDeserializer.java  
            CustomDateSerializer.java  
          GridFSClient.java  
          MongoDBClient.java  
          ImageSizeEnum.java  
  pom.xml  
  
whatsmars-fs-web  
  |-src  
    |-main  
      |-java  
        |-com.itlong.whatsmars.fs.web  
          |-controller  
            FileController.java  
          |-service  
            |-impl  
              FileServiceImpl.java  
            FileService.java  
      |-resource  
        log4j.xml  
        mongodb-config.properties  
        spring-context.xml  
        spring-mvc-servlet.xml  
        spring-service  
  pom.xml  

主要依赖:
Xml代码 收藏代码

<!-- 图片压缩工具 -->  
        <dependency>  
            <groupId>org.imgscalr</groupId>  
            <artifactId>imgscalr-lib</artifactId>  
            <version>4.2</version>  
        </dependency>  
  
        <dependency>  
            <groupId>org.mongodb</groupId>  
            <artifactId>mongo-java-driver</artifactId>  
            <version>3.0.0</version>  
        </dependency>  

Java代码 收藏代码

public class MongoDBConfig {  
  
    private String addresses;  
  
  
    private List<MongoDBCredential> credentials;  
  
    public String getAddresses() {  
        return addresses;  
    }  
  
    public void setAddresses(String addresses) {  
        this.addresses = addresses;  
    }  
  
    public List<MongoDBCredential> getCredentials() {  
        return credentials;  
    }  
  
    public void setCredentials(List<MongoDBCredential> credentials) {  
        this.credentials = credentials;  
    }  
  
    public List<MongoCredential> buildCredentials() {  
        List<MongoCredential> mongoCredentials = new ArrayList<MongoCredential>();  
        for(MongoDBCredential item : this.credentials) {  
            MongoCredential credential = MongoCredential.createCredential(item.getUsername(),item.getDatabaseName(),item.getPassword().toCharArray());  
            mongoCredentials.add(credential);  
        }  
        return mongoCredentials;  
    }  
  
    public List<ServerAddress> buildAddresses() throws Exception{  
        List<ServerAddress> serverAddresses = new ArrayList<ServerAddress>();  
        String[] sources = addresses.split(";");  
        for(String item : sources) {  
            String[] hp = item.split(":");  
            serverAddresses.add(new ServerAddress(hp[0],Integer.valueOf(hp[1])));  
        }  
        return serverAddresses;  
    }  
}  

Java代码 收藏代码

public class MongoDBCredential {  
  
    private String databaseName;  
  
    private String username;  
    private String password;  
  
    public String getDatabaseName() {  
        return databaseName;  
    }  
  
    public void setDatabaseName(String databaseName) {  
        this.databaseName = databaseName;  
    }  
  
    public String getUsername() {  
        return username;  
    }  
  
    public void setUsername(String username) {  
        this.username = username;  
    }  
  
    public String getPassword() {  
        return password;  
    }  
  
    public void setPassword(String password) {  
        this.password = password;  
    }  
}  

Java代码 收藏代码

public class MongoDBDriver {  
  
    private Properties properties;  
    /** 
     */  
private MongoClient mongo = null;  
  
    /** 
     */  
private Integer connectionsPerHost = 32;  
  
    private Integer threadsAllowedToBlockForConnectionMultiplier = 5;  
  
    private Integer maxWaitTime = 30000;  
    private Integer connectTimeout = 30000;  
    private Integer socketTimeout = 30000;  
  
    private Integer maxConnectionIdle = 6000;  
  
  
    private MongoDBConfig configuration;  
  
    public void setProperties(Properties properties) {  
        this.properties = properties;  
    }  
  
    public void setConfiguration(MongoDBConfig configuration) {  
        this.configuration = configuration;  
    }  
  
    public void init() throws Exception{  
        if(properties != null){  
  
            String perHost = properties.getProperty("mongodb.driver.connectionsPerHost");  
            ////////////  
if(StringUtils.isNotBlank(perHost)){  
                connectionsPerHost = Integer.valueOf(perHost);  
            }  
            ////////////  
String multiplier = properties.getProperty("mongodb.driver.threadsAllowedToBlockForConnectionMultiplier");  
            if(StringUtils.isNotBlank(multiplier)){  
                threadsAllowedToBlockForConnectionMultiplier = Integer.valueOf(multiplier);  
            }  
            /////////////  
String waitTime = properties.getProperty("mongodb.driver.maxWaitTime");  
            if(StringUtils.isNotBlank(waitTime)){  
                maxWaitTime = Integer.valueOf(waitTime);  
            }  
            ////////////  
String ctimeout = properties.getProperty("mongodb.driver.connectTimeout");  
            if(StringUtils.isNotBlank(ctimeout)){  
                connectTimeout = Integer.valueOf(ctimeout);  
            }  
            ////////////  
String stimeout = properties.getProperty("mongodb.driver.socketTimeout");  
            if(StringUtils.isNotBlank(stimeout)){  
                socketTimeout = Integer.valueOf(stimeout);  
            }  
            ////////////  
String mci = properties.getProperty("mongodb.driver.maxConnectionIdle");  
            if(StringUtils.isNotBlank(mci)){  
                maxConnectionIdle = Integer.valueOf(mci);  
            }  
        }  
        ////init,db check and connected.  
execute();  
  
    }  
  
    private void execute() throws Exception{  
        MongoClientOptions.Builder builder = MongoClientOptions.builder();  
        builder.connectionsPerHost(this.connectionsPerHost);  
        builder.threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier);  
        builder.socketKeepAlive(true);  
        builder.maxWaitTime(this.maxWaitTime);  
        builder.connectTimeout(this.connectTimeout);  
        builder.socketTimeout(this.socketTimeout);  
        builder.maxConnectionIdleTime(maxConnectionIdle);  
  
        MongoClientOptions options = builder.build();  
  
        this.mongo = new MongoClient(configuration.buildAddresses(), configuration.buildCredentials(),options);  
  
    }  
  
  
    public void close() {  
        mongo.close();  
    }  
  
    public Mongo getMongo() {  
        return mongo;  
    }  
  
    public MongoDatabase getDatabase(String dbName) {  
        return mongo.getDatabase(dbName);  
    }  
  
    /** 
     * old api 
     * @param dbName 
* @return 
*/  
public DB getDB(String dbName) {  
        return mongo.getDB(dbName);  
    }  
  
}  

Java代码 收藏代码

public class ObjectIdCreator{  
  
    public static String creator(){  
        return new ObjectId().toString();  
    }  
}  

Java代码 收藏代码

public class CustomDateDeserializer extends JsonDeserializer<Date> {  
  
    private static final String[] pattern = { "yyyy-MM-dd HH:mm:ss" };  
  
    @Override  
    public Date deserialize(JsonParser arg0, DeserializationContext arg1)  
            throws IOException, JsonProcessingException {  
        if (JsonToken.VALUE_STRING.equals(arg0.getCurrentToken())) {  
            try {  
                return DateUtils.parseDate(arg0.getText(), pattern);  
            } catch (ParseException e) {  
                e.printStackTrace();  
            }  
        }  
        return null;  
    }  
}  

Java代码 收藏代码

public class CustomDateSerializer extends JsonSerializer<Date> {    
  private static final String pattern = "yyyy-MM-dd HH:mm:ss";  
  
  @Override    
  public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {    
    jgen.writeString(DateFormatUtils.format(value, pattern));  
  }    
}  

Java代码 收藏代码

public class MongoDBClient {  
  
    protected MongoDBDriver mongoDBDriver;  
  
    protected String databaseName;  
  
    public void setMongoDBDriver(MongoDBDriver mongoDBDriver) {  
        this.mongoDBDriver = mongoDBDriver;  
    }  
  
  
  
    public void setDatabaseName(String databaseName) {  
        this.databaseName = databaseName;  
    }  
  
    public MongoCollection<Document> getCollection(String collectionName) {  
        MongoDatabase db = mongoDBDriver.getDatabase(this.databaseName);  
        return db.getCollection(collectionName);  
    }  
  
    public MongoDatabase getDatabase() {  
        return mongoDBDriver.getDatabase(this.databaseName);  
    }  
  
  
    public static void main(String[] args) throws Exception{  
  
        MongoDBDriver mongoDBDriver = new MongoDBDriver();  
        try{  
            MongoDBConfig mongoDBConfig = new MongoDBConfig();  
            //mongoDBConfig.setAddresses("61.171.123.234:27017");  
            mongoDBConfig.setAddresses("61.171.123.234:27017");  
            List<MongoDBCredential> credentials = new ArrayList<MongoDBCredential>();  
            MongoDBCredential credential = new MongoDBCredential();  
            credential.setDatabaseName("whatsmars-common");  
            credential.setUsername("whatsmars");  
            //credential.setPassword("haodai.com");  
            credential.setPassword("passwordiscommon");  
            credentials.add(credential);  
            mongoDBConfig.setCredentials(credentials);  
            mongoDBDriver.setConfiguration(mongoDBConfig);  
            mongoDBDriver.init();  
            MongoDBClient client = new MongoDBClient();  
            client.setDatabaseName("whatsmars-common");  
            client.setMongoDBDriver(mongoDBDriver);  
            ListCollectionsIterable<Document> documents = client.getDatabase().listCollections();  
            MongoCursor<Document> it = documents.iterator();  
            while (it.hasNext()) {  
                Document item = it.next();  
                System.out.println(item.toJson());  
            }  
            it.close();  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            mongoDBDriver.close();  
        }  
    }  
}  

Java代码 收藏代码

public class GridFSClient extends MongoDBClient{  
  
    private GridFS _gridFS = null;  
  
    private Object lock = new Object();  
  
    protected static final String[] IMAGE_FORMAT = {"jpg","jpeg","png"};  
  
  
    public void setMongoDBDriver(MongoDBDriver mongoDBDriver) {  
        this.mongoDBDriver = mongoDBDriver;  
    }  
  
    public GridFS getInstance() {  
        if(_gridFS != null) {  
            return _gridFS;  
        }  
        synchronized (lock) {  
            if(_gridFS != null) {  
                return _gridFS;  
            }  
            _gridFS = new GridFS(mongoDBDriver.getDB(this.databaseName));  
            return _gridFS;  
        }  
  
    }  
  
    public void close() {  
        mongoDBDriver.close();  
    }  
  
    /** 
     * 
     * @param inputStream 文件流 
     * @param format 文件格式,“pdf”,“png”等,不包含后缀符号“.” 
     * @return 
     */  
    public String saveFile(InputStream inputStream,String format,String uid) {  
        try {  
            GridFS gridFS = getInstance();  
  
            //随机生成文件名称,多次重试  
            String filename = this.randomFileName();  
            //如果有文件重复,则重新生成filename  
            while (true) {  
                GridFSDBFile _current = gridFS.findOne(filename);  
                //如果文件不存在,则保存操作  
                if (_current == null) {  
                    break;  
                }  
                filename = this.randomFileName();  
            }  
  
            GridFSInputFile file = gridFS.createFile(inputStream, filename);  
            if(format != null) {  
                file.put("format", format);  
            }  
            if(uid != null) {  
                file.put("uid",uid);  
            }  
            file.put("content-type","application/octet-stream");  
            file.save();  
            return concat(filename,format);  
        }catch (Exception e) {  
  
            throw new RuntimeException(e);  
        } finally {  
            try{  
                inputStream.close();  
            }catch (Exception ex) {  
                //  
            }  
        }  
    }  
  
    private String concat(String filename,String format) {  
        if(format == null) {  
            return filename;  
        }  
        if(format.startsWith(".")) {  
            return filename + format;  
        }  
        return filename + "." + format;  
    }  
  
    private String randomFileName() {  
        return RandomStringUtils.random(32, true, true).toLowerCase();  
    }  
  
    public void delete(String filename) {  
        GridFS gridFS = getInstance();  
        gridFS.remove(filename);  
    }  
  
    public InputStream getFile(String filename) {  
        GridFS gridFS = getInstance();  
        GridFSDBFile _current = gridFS.findOne(filename);  
        if(_current == null) {  
            return null;  
        }  
        return _current.getInputStream();  
    }  
  
    public InputStream getImage(String filename,String path) throws Exception{  
        //获取最大边,等比缩放  
        if(ImageSizeEnum.valueOfPath(path) == null) {  
            return null;  
        }  
  
        GridFS gridFS = getInstance();  
        GridFSDBFile _current = gridFS.findOne(filename);  
        if(_current == null) {  
            return null;  
        }  
  
        int size = ImageSizeEnum.valueOfPath(path).size;  
  
        int max = (Integer)_current.get("max");//图片的实际尺寸  
  
        InputStream result = null;  
        //裁剪  
        if(size < max) {  
            InputStream inputStream = _current.getInputStream();  
            BufferedImage image = ImageIO.read(inputStream);  
  
            inputStream.close();  
            ByteArrayOutputStream bos = new ByteArrayOutputStream();  
            BufferedImage thumbnail = Scalr.resize(image, size);//保留最大尺寸  
            String format = (String) _current.get("format");  
            ImageIO.write(thumbnail, format, bos);  
            result = new ByteArrayInputStream(bos.toByteArray());  
        } else {  
            result = _current.getInputStream();  
        }  
  
        return result;  
    }  
  
  
    /** 
     * 
     * @param inputStream 输入流 
     * @return 
     * @throws Exception 
     */  
    public String saveImage(InputStream inputStream,String uid) throws Exception{  
  
        BundleEntry bundleEntry = this.drain(inputStream);  
        if(bundleEntry == null) {  
            throw new RuntimeException("file isn't a image!");  
        }  
  
        ByteArrayInputStream bis = bundleEntry.inputStream;  
  
        String _currentFileName = this.isExistedImage(bundleEntry);  
  
        //如果文件md5已存在  
        if(_currentFileName != null) {  
            return _currentFileName;  
        }  
  
        String format = bundleEntry.format;  
        GridFS gridFS = getInstance();  
        String filename = this.randomFileName();  
        //检测文件名称  
        while(true){  
            GridFSDBFile _current = gridFS.findOne(filename);  
            //如果文件不存在,则保存操作  
            if (_current == null) {  
                break;  
            }  
            //否则,重新生成文件名称  
            filename = randomFileName();  
        }  
        //图片处理  
        bis.reset();  
  
        //保存原图  
        GridFSInputFile _inputFile = gridFS.createFile(bis, filename);  
        if(uid != null) {  
            _inputFile.put("uid", uid);  
        }  
        _inputFile.put("max",bundleEntry.max);  
        _inputFile.put("crc",bundleEntry.crc);  
        _inputFile.put("format",format);  
        _inputFile.put("md5_source",bundleEntry.md5);  
        _inputFile.save();  
  
        return concat(filename,format);  
  
    }  
  
    private String isExistedImage(BundleEntry entry) {  
        GridFS gridFS = getInstance();  
        DBObject query = new BasicDBObject();  
        query.put("crc",entry.crc);  
        query.put("md5_source",entry.md5);  
        GridFSDBFile _current = gridFS.findOne(query);  
        //根据MD5值查询,检测是否存在  
        if(_current == null) {  
            return null;  
        }  
        String format = (String)_current.get("format");  
        if(format.startsWith(".")) {  
            return _current.getFilename() + format;  
        }  
        return _current.getFilename() + "." + format;  
    }  
  
    /** 
     * 因为图片的stream需要reset,所以需要将流全部汲取 
     * @param inputStream 
     * @return 
     * @throws Exception 
     */  
    protected BundleEntry drain(InputStream inputStream) throws Exception{  
        //  
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        //计算源文件的md5、crc,以防止图片的重复上传  
        Adler32 crc = new Adler32();  
        try{  
            while(true) {  
                int _c = inputStream.read();  
                if(_c == -1) {  
                    break;  
                }  
                bos.write(_c);  
                crc.update(_c);  
            }  
  
        }catch (Exception e) {  
            throw new RuntimeException(e);  
        } finally {  
            inputStream.close();  
        }  
  
        //第一步:图片格式  
        List<String> formats = new ArrayList<String>();//  
        ImageInputStream imageInputStream = ImageIO.createImageInputStream(new ByteArrayInputStream(bos.toByteArray()));  
        imageInputStream.mark();  
        try {  
            Iterator<ImageReader> it = ImageIO.getImageReaders(imageInputStream);  
            while (it.hasNext()) {  
                ImageReader reader = it.next();  
                String format  = reader.getFormatName().toLowerCase();  
                if(ArrayUtils.contains(IMAGE_FORMAT, format)) {  
                    formats.add(format);  
                }  
            }  
        }catch (Exception ex) {  
            //  
        }  
  
        //如果格式不合法,则直接返回  
        if(formats.isEmpty()) {  
            try {  
                imageInputStream.close();  
            } catch (Exception e) {  
                //  
            }  
            return null;  
        }  
  
        String md5 = DigestUtils.md5Hex(bos.toByteArray());//求原始图片的MD5,和crc  
        System.out.println("md5:" + md5);  
        imageInputStream.reset();  
  
        BufferedImage image = ImageIO.read(imageInputStream);  
  
        //获取最大边,等比缩放  
        int max = Math.max(image.getHeight(), image.getWidth());  
  
        bos = new ByteArrayOutputStream();  
        //如果尺寸超过最大值,则resize  
        if(max > ImageSizeEnum.PIXELS_MAX.size) {  
            max = ImageSizeEnum.PIXELS_MAX.size;  
        }  
        String format = formats.get(0);  
        BufferedImage thumbnail = Scalr.resize(image, max);//保留最大尺寸  
        ImageIO.write(thumbnail, format, bos);  
  
        return new BundleEntry(new ByteArrayInputStream(bos.toByteArray()),md5,crc.getValue(),format,max);  
    }  
  
  
    protected class BundleEntry {  
        String md5;  
        long crc;  
        String format;  
        int max;  
        ByteArrayInputStream inputStream;  
        BundleEntry(ByteArrayInputStream inputStream,String md5,long crc,String format,int max) {  
            this.md5 = md5;  
            this.crc = crc;  
            this.inputStream = inputStream;  
            this.format = format;  
            this.max = max;  
        }  
    }  
  
  
  
    public static void main(String[] args) throws Exception{  
  
        MongoDBDriver mongoDBDriver = new MongoDBDriver();  
        try {  
            GridFSClient client = new GridFSClient();  
            MongoDBConfig mongoDBConfig = new MongoDBConfig();  
            //mongoDBConfig.setAddresses("61.172.238.149:27017");  
            mongoDBConfig.setAddresses("61.172.240.58:27017");  
            List<MongoDBCredential> credentials = new ArrayList<MongoDBCredential>();  
            MongoDBCredential credential = new MongoDBCredential();  
            credential.setDatabaseName("whatsmars-fs");  
            credential.setUsername("whatsmars");  
            //credential.setPassword("haodai.com");  
            credential.setPassword("passwordisfs");  
            credentials.add(credential);  
            mongoDBConfig.setCredentials(credentials);  
            mongoDBDriver.setConfiguration(mongoDBConfig);  
            mongoDBDriver.init();  
            client.setDatabaseName("whatsmars-fs");  
            client.setMongoDBDriver(mongoDBDriver);  
            testUpload(client);  
            //testClear(client.getInstance());  
            //testGetImage(client.getInstance(),"xhgcguccxumuyl9hzdombgfvzgriv7rf",null);  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            mongoDBDriver.close();  
        }  
  
    }  
  
  
    protected static void testClear(GridFS gridFS) {  
        DBCursor cursor = gridFS.getFileList();  
        while (cursor.hasNext()) {  
            DBObject dbObject = cursor.next();  
            String filename = (String)cursor.next().get("filename");  
            System.out.println(filename);  
            System.out.println(dbObject.toString());  
            gridFS.remove(filename);  
        }  
        cursor.close();  
    }  
  
  
    protected static void testUpload(GridFSClient client) throws Exception{  
        FileInputStream inputStream = new FileInputStream(new File("/data/tmp/222222222.jpg"));  
  
        try {  
  
            String filename = client.saveImage(inputStream, null);  
            System.out.println(filename);  
            String source = filename.substring(0,filename.lastIndexOf("."));  
            System.out.println(source);  
            InputStream result = client.getImage(source, "x4");  
            if(result == null) {  
                System.out.println("not found!");  
            }  
            //vejibw36famkscjyksgke7bugzonnyan  
  
            FileOutputStream outputStream = new FileOutputStream("/data/tmp/" + filename);  
            while (true) {  
                int i = result.read();  
                if( i == -1) {  
                    break;  
                }  
                outputStream.write(i);  
            }  
            outputStream.flush();  
            outputStream.close();  
            result.close();  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            inputStream.close();  
        }  
  
    }  
  
    protected static void testGetImage(GridFS gridFS,String filename,String path) {  
        DBObject query = new BasicDBObject();  
        query.put("md5_source","9e131ae4ed7337d4712650229b827725");  
        GridFSDBFile file = gridFS.findOne(query);  
        if(file != null) {  
            System.out.println(file.getFilename());  
        }  
    }  
  
}  

Java代码 收藏代码

public enum ImageSizeEnum {  
  
    PIXELS_200(200, "x2"),  
    PIXELS_400(400, "x4"),  
    PIXELS_600(600, "x6"),  
    PIXELS_800(800, "x8"),  
  
    PIXELS_MAX(1024, "xm");//最大1024  
    public int size;  
  
    public String path;  
  
    ImageSizeEnum(int size, String path) {  
        this.size = size;  
        this.path = path;  
    }  
  
    public static ImageSizeEnum valueOfPath(String path) {  
        if(path == null) {  
            return  null;  
        }  
        for(ImageSizeEnum e : ImageSizeEnum.values()) {  
            if(e.path.equalsIgnoreCase(path)) {  
                return e;  
            }  
        }  
        return null;  
    }  
}  

mongodb-config.properties:
Xml代码 收藏代码

mongodb.driver.connectionsPerHost=32  
mongodb.driver.threadsAllowedToBlockForConnectionMultiplier=5  
mongodb.driver.maxWaitTime=30000  
mongodb.driver.connectTimeout=30000  
mongodb.driver.socketTimeout=30000  
mongodb.driver.maxConnectionIdle=60000  

spring-context.xml:
Xml代码 收藏代码

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"  
        default-autowire="byName">  
  
    <import resource="spring-service.xml" />  
</beans>  

spring-service.xml:
Xml代码 收藏代码

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"   
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xsi:schemaLocation="  
        http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context-3.2.xsd"  
    default-autowire="byName">  
  
    <context:component-scan base-package="com.itlong.whatsmars.fs.web.service" />  
  
    <bean id="mongodbProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">  
        <property name="locations">  
            <list>  
                <value>classpath:mongodb-config.properties</value>  
            </list>  
        </property>  
    </bean>  
  
    <bean id="mongodbDriver" class="com.itlong.whatsmars.common.mongo.object.MongoDBDriver" init-method="init" destroy-method="close">  
        <property name="properties" ref="mongodbProperties"/>  
        <property name="configuration">  
            <bean class="com.itlong.whatsmars.common.mongo.object.MongoDBConfig">  
                <property name="addresses" value="${whatsmars.mongodb.filesystem.addresses}"/>  
                <property name="credentials">  
                    <list>  
                        <bean class="com.itlong.whatsmars.common.mongo.object.MongoDBCredential">  
                            <property name="databaseName" value="${whatsmars.mongodb.filesystem.dbname}"/>  
                            <property name="username" value="${whatsmars.mongodb.filesystem.username}"/>  
                            <property name="password" value="${whatsmars.mongodb.filesystem.password}"/>  
                        </bean>  
                    </list>  
                </property>  
  
            </bean>  
  
        </property>  
    </bean>  
  
    <bean id="gridFSClient" class="com.itlong.whatsmars.common.mongo.GridFSClient">  
        <property name="mongoDBDriver" ref="mongodbDriver"/>  
        <property name="databaseName" value="${whatsmars.mongodb.filesystem.dbname}"/>  
    </bean>  
  
</beans>  

spring-mvc-servlet.xml:
Xml代码 收藏代码

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xmlns:context="http://www.springframework.org/schema/context"  
       xmlns:mvc="http://www.springframework.org/schema/mvc"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
           http://www.springframework.org/schema/context  
           http://www.springframework.org/schema/context/spring-context-3.2.xsd  
           http://www.springframework.org/schema/mvc  
           http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">  
  
    <mvc:annotation-driven>  
        <mvc:message-converters>  
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">  
                <property name = "supportedMediaTypes">  
                    <list>  
                        <value>text/plain;charset=UTF-8</value>  
                        <value>text/html;charset=UTF-8</value>  
                    </list>  
                </property>  
            </bean>  
  
        </mvc:message-converters>  
    </mvc:annotation-driven>  
    <context:component-scan base-package="com.itlong.whatsmars.fs.web.controller" />  
  
  
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>  
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>  
  
    <bean id="exceptionResolver" class="ExceptionHandler"/>  
  
</beans>  

Java代码 收藏代码

@Controller  
public class FileController {  
  
    private static final int SIZE = 1028576;//1M  
  
    @Autowired  
    private FileService fileService;  
  
    @RequestMapping("/file_upload")  
    @ResponseBody  
    public String uploadFile(@RequestParam(value = "format",required = false)String format,  
                             @RequestParam(value = "uid")String uid,  
                             @RequestParam("token")String token,  
                             HttpServletRequest request) {  
  
        String source = DESUtils.decrypt(token, CommonConstants.FS_SECURITY_KEY);  
        if(!source.equals(uid)) {  
            return ResultHelper.renderAsJson(ResultCode.VALIDATE_FAILURE);  
        }  
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        try {  
            InputStream inputStream = request.getInputStream();//body inputstream  
            if (inputStream == null) {  
                return ResultHelper.renderAsJson(ResultCode.PARAMETER_ERROR);  
            }  
            int i = 0;  
            int maxSize = SIZE * 32;//最大32M  
            while (true) {  
                int _c = inputStream.read();  
                if (_c == -1) {  
                    break;  
                }  
                bos.write(_c);  
                i++;  
                if (i > maxSize) {  
                    inputStream.close();  
                    bos.close();  
                    return ResultHelper.renderAsJson(ResultCode.VALIDATE_FAILURE, "文件尺寸超过最大限制");  
                }  
            }  
            inputStream.close();  
        } catch (Exception e) {  
            return ResultHelper.renderAsJson(ResultCode.SYSTEM_ERROR);  
        }  
  
        //  
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
        Result result = this.fileService.uploadFile(bis, format,uid);  
        return ResultHelper.renderAsJson(result);  
    }  
  
  
    @RequestMapping("/image_upload")  
    @ResponseBody  
    public String uploadImage(@RequestParam("token")String token,  
                              @RequestParam("uid")String uid,  
                              @RequestParam(value = "return_size",required = false)Integer returnSize,  
                              HttpServletRequest request) {  
  
        String source = DESUtils.decrypt(token, CommonConstants.FS_SECURITY_KEY);  
        if(!source.equals(uid)) {  
            return ResultHelper.renderAsJson(ResultCode.VALIDATE_FAILURE);  
        }  
  
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        try {  
            InputStream inputStream = request.getInputStream();//body inputstream  
            if (inputStream == null) {  
                return ResultHelper.renderAsJson(ResultCode.PARAMETER_ERROR);  
            }  
            int i = 0;  
            int maxSize = 6 * SIZE;//最大6M  
            while (true) {  
                int _c = inputStream.read();  
                if (_c == -1) {  
                    break;  
                }  
                bos.write(_c);  
                i++;  
                if (i > maxSize) {  
                    inputStream.close();  
                    bos.close();  
                    return ResultHelper.renderAsJson(ResultCode.VALIDATE_FAILURE, "文件尺寸超过最大限制");  
                }  
            }  
            inputStream.close();  
        } catch (Exception e) {  
            return ResultHelper.renderAsJson(ResultCode.SYSTEM_ERROR);  
        }  
  
        //  
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
        Result result = this.fileService.uploadImage(bis,uid,returnSize);  
        return ResultHelper.renderAsJson(result);  
    }  
  
    @RequestMapping("/ds/{filename}")  
    @ResponseBody  
    public void displayFile(@PathVariable("filename")String filename,HttpServletResponse response) {  
        Result result = this.fileService.displayFile(filename);  
        if(result.isSuccess()) {  
            InputStream stream = (InputStream)result.getModel("inputStream");  
            try {  
                OutputStream outputStream = response.getOutputStream();  
                if (stream != null) {  
                    BufferedInputStream bis = new BufferedInputStream(stream, 128);  
                    while (true) {  
                        int _current = bis.read();  
                        if (_current < 0) {  
                            break;  
                        }  
                        outputStream.write((byte) _current);  
                    }  
                }  
            } catch (Exception e) {  
                //  
            } finally {  
                try {  
                    stream.close();  
                }catch (Exception e) {  
                    //  
                }  
            }  
        }  
    }  
  
    @RequestMapping("/ds/{path}/{filename}")  
    @ResponseBody  
    public void displayImage(@PathVariable("filename")String filename,  
                             @PathVariable("path")String path,  
                             HttpServletResponse response) {  
  
        Result result = this.fileService.displayImage(filename,path);  
        if(result.isSuccess()) {  
            InputStream stream = (InputStream)result.getModel("inputStream");  
            try {  
                OutputStream outputStream = response.getOutputStream();  
                if (stream != null) {  
                    BufferedInputStream bis = new BufferedInputStream(stream, 128);  
                    while (true) {  
                        int _current = bis.read();  
                        if (_current < 0) {  
                            break;  
                        }  
                        outputStream.write((byte) _current);  
                    }  
                }  
//                String timestamp = (String)result.getModel("timestamp");  
//                if(timestamp != null) {  
//                    response.addDateHeader("Last-Modified",Long.valueOf(timestamp));  
//                }  
            } catch (Exception e) {  
                //  
            } finally {  
                try {  
                    stream.close();  
                }catch (Exception e) {  
                    //  
                }  
            }  
        }  
    }  
  
}  

Java代码 收藏代码

public interface FileService {  
  
    /** 
     * 上传文件,制定文件的格式 
     * @param inputStream 输入流 
     * @Param format 文件格式后缀 
     * @param uid 文件上传者 
     * 
     */  
    public Result uploadFile(InputStream inputStream, String format, String uid);  
  
    /** 
     * 图片上传 
     * @param inputStream 
     * @param returnSize 返回接近此size的url全路径 
     */  
    public Result uploadImage(ByteArrayInputStream inputStream, String uid, Integer returnSize);  
  
    /** 
     * 删除文件 
     * @param filename 
     * @return 
     */  
    public Result delete(String filename);  
  
    /** 
     * 获取文件 
     * @param filename 
     * @return 
     */  
    public Result displayFile(String filename);  
  
    public Result displayImage(String filename, String path);  
}  

Java代码 收藏代码

@Service  
public class FileServiceImpl implements FileService {  
  
    protected static final Logger logger = Logger.getLogger(FileService.class);  
  
    @Autowired  
    private GridFSClient gridFSClient;  
  
    @Override  
    public Result uploadFile(InputStream inputStream, String format,String uid) {  
        Result result = new Result();  
        try {  
            String filename = gridFSClient.saveFile(inputStream,format,uid);  
            result.addModel("filename",filename);  
            result.setSuccess(true);  
        } catch (Exception e) {  
            logger.error("upload file error,",e);  
            result.setResultCode(ResultCode.SYSTEM_ERROR);  
            result.setMessage("文件上传失败");  
        }  
        return result;  
    }  
  
    @Override  
    public Result uploadImage(ByteArrayInputStream inputStream,String uid,Integer returnSize) {  
        Result result = new Result();  
        try {  
            String filename = gridFSClient.saveImage(inputStream,uid);  
            result.addModel("filename",filename);  
  
            if(returnSize != null && returnSize > 0) {  
                //找出符合returnSize的path  
                for (ImageSizeEnum e : ImageSizeEnum.values()) {  
                    if (e.size >= returnSize) {  
                        result.addModel("uri",e.path + "/" + filename);  
                    }  
                }  
                //返回最大尺寸  
                result.addModel("uri",ImageSizeEnum.PIXELS_MAX.path + "/" + filename);  
            }  
            result.setSuccess(true);  
        } catch (Exception e) {  
            logger.error("upload image error,",e);  
            result.setResultCode(ResultCode.SYSTEM_ERROR);  
            result.setMessage("图片上传失败");  
        }  
        return result;  
    }  
  
    @Override  
    public Result delete(String filename) {  
        Result result = new Result();  
        try {  
            gridFSClient.delete(filename);  
            result.addModel("filename",filename);  
            result.setSuccess(true);  
        } catch (Exception e) {  
            logger.error("delete file error,",e);  
            result.setResultCode(ResultCode.SYSTEM_ERROR);  
            result.setMessage("文件删除失败");  
        }  
        return result;  
    }  
  
    @Override  
    public Result displayImage(String filename,String path) {  
        Result result = new Result();  
        try {  
            InputStream inputStream = gridFSClient.getImage(filename,path);  
            if(inputStream != null) {  
                result.addModel("inputStream", inputStream);  
                result.setSuccess(true);  
            }  
        } catch (Exception e) {  
            result.setResultCode(ResultCode.SYSTEM_ERROR);  
        }  
        return result;  
    }  
  
  
    @Override  
    public Result displayFile(String filename) {  
        Result result = new Result();  
        try {  
            InputStream inputStream = gridFSClient.getFile(filename);  
            if(inputStream != null) {  
                result.addModel("inputStream", inputStream);  
                result.setSuccess(true);  
            }  
        } catch (Exception e) {  
            result.setResultCode(ResultCode.SYSTEM_ERROR);  
        }  
        return result;  
    }  
}  

代码见 http://java.toutiao.im

原文链接:[http://wely.iteye.com/blog/2382451]

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
6月前
|
存储 缓存 NoSQL
MongoDB内部的存储原理
这篇文章详细介绍了MongoDB的内部存储原理,包括存储引擎WiredTiger的架构、btree与b+tree的比较、cache机制、page结构、写操作流程、checkpoint和WAL日志,以及分布式存储的架构。
257 1
MongoDB内部的存储原理
|
5月前
|
存储 NoSQL MongoDB
数据的存储--MongoDB文档存储(二)
数据的存储--MongoDB文档存储(二)
139 2
|
1月前
|
存储 NoSQL MongoDB
数据库数据恢复—MongoDB数据库迁移过程中丢失文件的数据恢复案例
某单位一台MongoDB数据库由于业务需求进行了数据迁移,数据库迁移后提示:“Windows无法启动MongoDB服务(位于 本地计算机 上)错误1067:进程意外终止。”
|
24天前
|
存储 NoSQL 安全
客户说|知乎核心业务MongoDB集群的平滑上云迁移实践
客户说|知乎核心业务MongoDB集群的平滑上云迁移实践
|
8月前
|
SQL NoSQL 数据管理
数据管理DMS使用问题之如何批量导入MongoDB的数据文件
阿里云数据管理DMS提供了全面的数据管理、数据库运维、数据安全、数据迁移与同步等功能,助力企业高效、安全地进行数据库管理和运维工作。以下是DMS产品使用合集的详细介绍。
|
3月前
|
存储 NoSQL MongoDB
【赵渝强老师】MongoDB逻辑存储结构
MongoDB的逻辑存储结构由数据库(Database)、集合(Collection)和文档(Document)组成,形成层次化数据模型。用户通过mongoshell或应用程序操作这些结构。视频讲解及结构图详见下文。
138 3
|
4月前
|
存储 NoSQL 关系型数据库
【赵渝强老师】MongoDB的存储结构
MongoDB 是一个可移植的 NoSQL 数据库,支持跨平台运行。其逻辑存储结构包括数据库、集合和文档,而物理存储结构则由命名空间文件、数据文件和日志文件组成。视频讲解和示意图进一步解释了这些概念。
163 5
|
4月前
|
NoSQL Cloud Native atlas
探索云原生数据库:MongoDB Atlas 的实践与思考
【10月更文挑战第21天】本文探讨了MongoDB Atlas的核心特性、实践应用及对云原生数据库未来的思考。MongoDB Atlas作为MongoDB的云原生版本,提供全球分布式、完全托管、弹性伸缩和安全合规等优势,支持快速部署、数据全球化、自动化运维和灵活定价。文章还讨论了云原生数据库的未来趋势,如架构灵活性、智能化运维和混合云支持,并分享了实施MongoDB Atlas的最佳实践。
|
5月前
|
NoSQL Cloud Native atlas
探索云原生数据库:MongoDB Atlas 的实践与思考
【10月更文挑战第20天】本文探讨了MongoDB Atlas的核心特性、实践应用及对未来云原生数据库的思考。MongoDB Atlas作为云原生数据库服务,具备全球分布、完全托管、弹性伸缩和安全合规等优势,支持快速部署、数据全球化、自动化运维和灵活定价。文章还讨论了实施MongoDB Atlas的最佳实践和职业心得,展望了云原生数据库的发展趋势。