可能很多人会问为何要用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
相关推荐
MongoDB的GridFS是存储大文件(如图片、视频)的标准,它将每个文件分割成多个小块(chunks),然后分别存储,以提高性能和容错性。在Spring Data MongoDB中,我们可以通过`GridFsTemplate`来实现GridFS的操作,如上...
GridFS 是 MongoDB 提供的一种用于存储和检索大型文件(如图片、视频等)的标准机制,将大文件分成多个小块存储在 MongoDB 的集合中,以提高效率和可靠性。 在这个"mongodb+GridFS文件的上传下载删除DEMO"项目中,...
最后,"MongoDB Manual_files" 目录很可能包含了手册中的图片、样式表等辅助文件,用于增强阅读体验和理解。 总的来说,这个压缩包提供了一个全面的学习路径,从基础到高级,涵盖了MongoDB的各个方面。无论是新手...
- **网格FS(GridFS)**:MongoDB内置了文件存储系统GridFS,可以用于存储大文件,如图片、视频等。 - **SSL支持**:如安装包名称所示,此版本的MongoDB支持SSL加密,确保数据传输的安全性。 学习和使用MongoDB,...
GridFS 是 MongoDB 的一个模块,用于存储和检索大文件,如图片、视频等。 **9.4 常见问题解答** 这部分内容解答了关于 MongoDB 存储方面的一些常见问题。 #### 十、复制 **10.1 复制介绍** 复制是 MongoDB 中一...
1. **文档数据库**:MongoDB存储数据以JSON格式的文档为主,这种文档由键值对组成,具有良好的可读性和灵活性。文档可以包含嵌套结构,使得数据模型更加丰富。 2. **集合与数据库**:在MongoDB中,数据库是存储数据...
8. **GridFS**:MongoDB的GridFS是一个用于存储和检索大文件的规范,如图片或视频。它将大文件分割成多个小块存储在两个集合中,方便管理和检索。 9. **驱动程序(Driver)**:MongoDB有多种官方和社区支持的驱动...
GridFS是MongoDB提供的一种存储大型文件(如图片、视频等)的标准方法,它将大文件分割成多个小块(chunks),每个chunk存储在单独的文档中。 在MongoDB中,删除GridFS文件通常涉及两个集合:`fs.chunks`和`fs....
在本项目中,MongoDB存储学生的各种信息,如姓名、年龄、班级等。 **四、art-template模板引擎** art-template是Node.js的一个高性能的JavaScript模板引擎,用于将数据渲染到HTML页面。在这个系统中,art-template...
10. **GridFS**:MongoDB提供的文件存储系统,用于存储和检索大文件,如图片或视频。 11. **命令行工具**:如mongo shell的使用,以及mongodump、mongorestore、mongostat等实用工具的介绍。 12. **安全性**:包括...
8. **GridFS**:MongoDB 的 GridFS 功能用于存储和检索大型文件,如图片或视频。它将大文件分割成小块存储在多个文档中,提供了一种高效且灵活的文件存储解决方案。 9. **命令行工具**:MongoDB 提供了 `mongo` ...
通过这个项目,你可以学习到如何结合Node.js的灵活性、Express的简洁性和MongoDB的高效存储,构建一个完整的Web应用程序。这不仅是提升个人技能的好机会,也是实际项目开发中的常见技术栈。在实践中,你还可以进一步...
6. **网格FS(GridFS)**:用于存储和检索大文件,如图片或视频,将大文件拆分为多个小块存储。 7. **高性能**:MongoDB使用内存映射技术,读写速度快,适合实时数据处理。 在项目开发中,MongoDB的优势在于其易用...
- `public`:存放静态资源,如CSS样式表、JavaScript文件和图片。 - `views`:存放模板文件,如EJS或Pug,用于动态渲染HTML页面。 - `routes`:存放路由文件,定义了不同的URL路径及其对应的处理函数。 - `...
MongoDB、Gin和WebSocket是...综上所述,这个项目展示了如何结合MongoDB、Gin和WebSocket构建一个实时的Web通信系统,涵盖了数据存储、后端API开发和实时通信的核心技术,对于学习和实践Web开发有着很高的参考价值。
在这个“MongoDB之Java使用例子”中,我们将深入探讨如何在Java环境中操作MongoDB数据库,包括增、删、改、查(CRUD)操作以及图像数据的存储和检索。 首先,Java与MongoDB的交互主要通过MongoDB的Java驱动程序实现...
MongoDB 使用手册 MongoDB 是一个高性能、开源、无模式的文档型数据库,适用于现代应用程序开发。它以其灵活的数据模型、强大的查询能力以及...通过阅读和实践本手册,你将能够熟练地运用MongoDB进行数据存储和处理。
`public`目录通常是静态资源文件的存放位置,如CSS样式表、JavaScript脚本、图片等。在Express框架中,这个目录默认会被设置为静态文件服务器,直接向客户端发送这些文件。 `models`目录则用于存放与数据库交互的...
GridFS是MongoDB用于存储大型文件(如图片、视频)的分布式文件系统。通过GridFS,你可以将大文件分割成小块存储,并能轻松地进行上传、下载和管理。 6. 示例项目: "AddressBookForm.dcu"和"AddressBookForm.ddp...