`
IXHONG
  • 浏览: 449437 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

mongodb存储图片和文件实践

阅读更多

  可能很多人会问为何要用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

 主要依赖:

<!-- 图片压缩工具 -->
        <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>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.13</version>
        </dependency>

 

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;
    }
}

 

 

 

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;
    }
}

 


 

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);
    }

}

 

 

public class ObjectIdCreator{

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

  

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;
	}
}

 

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));
  }  
}

 

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();
        }
    }
}

 

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());
        }
    }

}

 

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:

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 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 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 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>

 

@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) {
                    //
                }
            }
        }
    }

}

 

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);
}

 

@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

0
1
分享到:
评论

相关推荐

    spring boot websocket , mongoDBd存文件 图片服务器

    MongoDB的GridFS是存储大文件(如图片、视频)的标准,它将每个文件分割成多个小块(chunks),然后分别存储,以提高性能和容错性。在Spring Data MongoDB中,我们可以通过`GridFsTemplate`来实现GridFS的操作,如上...

    mongodb+GridFS文件的上传下载删除DEMO

    GridFS 是 MongoDB 提供的一种用于存储和检索大型文件(如图片、视频等)的标准机制,将大文件分成多个小块存储在 MongoDB 的集合中,以提高效率和可靠性。 在这个"mongodb+GridFS文件的上传下载删除DEMO"项目中,...

    MongoDB 手册和MongoDB权威指南

    最后,"MongoDB Manual_files" 目录很可能包含了手册中的图片、样式表等辅助文件,用于增强阅读体验和理解。 总的来说,这个压缩包提供了一个全面的学习路径,从基础到高级,涵盖了MongoDB的各个方面。无论是新手...

    mongoDB安装包

    - **网格FS(GridFS)**:MongoDB内置了文件存储系统GridFS,可以用于存储大文件,如图片、视频等。 - **SSL支持**:如安装包名称所示,此版本的MongoDB支持SSL加密,确保数据传输的安全性。 学习和使用MongoDB,...

    mongodb3.2.4说明文档

    GridFS 是 MongoDB 的一个模块,用于存储和检索大文件,如图片、视频等。 **9.4 常见问题解答** 这部分内容解答了关于 MongoDB 存储方面的一些常见问题。 #### 十、复制 **10.1 复制介绍** 复制是 MongoDB 中一...

    mongodbDemo

    1. **文档数据库**:MongoDB存储数据以JSON格式的文档为主,这种文档由键值对组成,具有良好的可读性和灵活性。文档可以包含嵌套结构,使得数据模型更加丰富。 2. **集合与数据库**:在MongoDB中,数据库是存储数据...

    MongoDB;学习资料

    8. **GridFS**:MongoDB的GridFS是一个用于存储和检索大文件的规范,如图片或视频。它将大文件分割成多个小块存储在两个集合中,方便管理和检索。 9. **驱动程序(Driver)**:MongoDB有多种官方和社区支持的驱动...

    Mongodb批量删除gridfs文件实例

    GridFS是MongoDB提供的一种存储大型文件(如图片、视频等)的标准方法,它将大文件分割成多个小块(chunks),每个chunk存储在单独的文档中。 在MongoDB中,删除GridFS文件通常涉及两个集合:`fs.chunks`和`fs....

    Node学生管理系统(Express+MongoDB)

    在本项目中,MongoDB存储学生的各种信息,如姓名、年龄、班级等。 **四、art-template模板引擎** art-template是Node.js的一个高性能的JavaScript模板引擎,用于将数据渲染到HTML页面。在这个系统中,art-template...

    MongoDB离线参考手册-菜鸟教程离线版

    10. **GridFS**:MongoDB提供的文件存储系统,用于存储和检索大文件,如图片或视频。 11. **命令行工具**:如mongo shell的使用,以及mongodump、mongorestore、mongostat等实用工具的介绍。 12. **安全性**:包括...

    MongoDB 入门教程 chm手册

    8. **GridFS**:MongoDB 的 GridFS 功能用于存储和检索大型文件,如图片或视频。它将大文件分割成小块存储在多个文档中,提供了一种高效且灵活的文件存储解决方案。 9. **命令行工具**:MongoDB 提供了 `mongo` ...

    node.js结合mongodb构建的web项目

    通过这个项目,你可以学习到如何结合Node.js的灵活性、Express的简洁性和MongoDB的高效存储,构建一个完整的Web应用程序。这不仅是提升个人技能的好机会,也是实际项目开发中的常见技术栈。在实践中,你还可以进一步...

    MongoDB经典概要(内附项目代码)

    6. **网格FS(GridFS)**:用于存储和检索大文件,如图片或视频,将大文件拆分为多个小块存储。 7. **高性能**:MongoDB使用内存映射技术,读写速度快,适合实时数据处理。 在项目开发中,MongoDB的优势在于其易用...

    NodeJS+Express+MongoDB简单博客系统

    - `public`:存放静态资源,如CSS样式表、JavaScript文件和图片。 - `views`:存放模板文件,如EJS或Pug,用于动态渲染HTML页面。 - `routes`:存放路由文件,定义了不同的URL路径及其对应的处理函数。 - `...

    mongoDB + gin + websocket 实现的一个即时通信系统.zip

    MongoDB、Gin和WebSocket是...综上所述,这个项目展示了如何结合MongoDB、Gin和WebSocket构建一个实时的Web通信系统,涵盖了数据存储、后端API开发和实时通信的核心技术,对于学习和实践Web开发有着很高的参考价值。

    MongoDB之Java使用例子

    在这个“MongoDB之Java使用例子”中,我们将深入探讨如何在Java环境中操作MongoDB数据库,包括增、删、改、查(CRUD)操作以及图像数据的存储和检索。 首先,Java与MongoDB的交互主要通过MongoDB的Java驱动程序实现...

    mongodb 使用手册

    MongoDB 使用手册 MongoDB 是一个高性能、开源、无模式的文档型数据库,适用于现代应用程序开发。它以其灵活的数据模型、强大的查询能力以及...通过阅读和实践本手册,你将能够熟练地运用MongoDB进行数据存储和处理。

    node+mongodb 建站攻略(一期)代码

    `public`目录通常是静态资源文件的存放位置,如CSS样式表、JavaScript脚本、图片等。在Express框架中,这个目录默认会被设置为静态文件服务器,直接向客户端发送这些文件。 `models`目录则用于存放与数据库交互的...

    mongo-delphi-driver-master.zip_mongo delphi driver_mongodb资料

    GridFS是MongoDB用于存储大型文件(如图片、视频)的分布式文件系统。通过GridFS,你可以将大文件分割成小块存储,并能轻松地进行上传、下载和管理。 6. 示例项目: "AddressBookForm.dcu"和"AddressBookForm.ddp...

Global site tag (gtag.js) - Google Analytics