使用jetty和mongodb实现简易网盘接口
依赖库:
1,jetty(提供http方式接口)
2,mongodb的java驱动(访问mongodb存取文件)
3,thumbnailator包,进行缩略图生成
4,commons-fileupload包及commons-io包用于处理文件上传
架构图:

入口代码如下:
package com.ciaos.vfs;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.thread.QueuedThreadPool; public class VfsServer {
public static void main(String[] args) throws Exception { SelectChannelConnector connector = new SelectChannelConnector();
connector.setHost("127.0.0.1");
connector.setPort(8080);
connector.setThreadPool(new QueuedThreadPool(200)); Server server = new Server();
server.setConnectors(new Connector[]{connector}); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/"); server.setHandler(context); context.addServlet(new ServletHolder(new VfsFileServlet()), "/file"); server.start();
server.join();
}
}
业务代码如下:
package com.ciaos.vfs; import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.List; import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import net.coobird.thumbnailator.Thumbnails; import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.bson.types.ObjectId; import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile; public class VfsFileServlet extends HttpServlet { /**
*
*/
private static final long serialVersionUID = 5586455171943232770L; private String tempPath = null;
private Mongo mongo = null; final private String MongoDbIp = "127.0.0.1";
final private Integer MongoDbPort = 27017; @Override
public void init() throws ServletException {
// TODO Auto-generated method stub tempPath = "/tmp/";
try {
mongo=new Mongo(MongoDbIp, MongoDbPort);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(-1);
}
super.init();
} @Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
String fileId = req.getParameter("id");
String MongoDbName = req.getParameter("type");
if(fileId == null || MongoDbName == null){
resp.sendError(400,"bad request");
return;
}
DB db=mongo.getDB(MongoDbName);
GridFS gridFS=new GridFS(db);
try{
gridFS.remove(new ObjectId(fileId));
}
catch(IllegalArgumentException ex){
resp.sendError(404,"file not found");
return;
}
} @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
String fileId = req.getParameter("id");
String MongoDbName = req.getParameter("type");
if(fileId == null || MongoDbName == null){
resp.sendError(400,"bad request");
return;
} DB db=mongo.getDB(MongoDbName);
GridFS gridFS=new GridFS(db); GridFSDBFile mongofile = null;
try{
mongofile = gridFS.find(new ObjectId(fileId));
}
catch(IllegalArgumentException ex){
resp.sendError(404,"file not found");
return;
} if(mongofile!=null){
resp.setHeader("Content-type", mongofile.getContentType());
resp.setHeader("Content-Disposition", "attachment; filename= "+mongofile.getFilename());
mongofile.put("viewtimes", (Integer)mongofile.get("viewtimes")+1);
ServletOutputStream out = resp.getOutputStream(); String dtype = req.getParameter("act");
if(dtype!=null && dtype.equals("preview")){
Integer width = 0, height = 0;
try{
width = Integer.parseInt(req.getParameter("w"));
height = Integer.parseInt(req.getParameter("h")); BufferedImage image = ImageIO.read(mongofile.getInputStream());
width = Math.min(width,image.getWidth());
height = Math.min(height,image.getHeight()); Thumbnails.of(mongofile.getInputStream())
.size(width, height)
.toOutputStream(out);
}
catch(NumberFormatException ex){
resp.sendError(400,"bad request");
return;
}
}else{
InputStream input = mongofile.getInputStream();
byte[] buffer = new byte[64*1024];
for(;;)
{
int count = input.read(buffer);
if (count < 0)
break;
out.write(buffer,0,count);
}
} out.flush();
out.close();
mongofile.save();
}else{
resp.sendError(500,"internal server error");
}
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
doPut(req, resp);
} @Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
req.setCharacterEncoding("utf-8");
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(tempPath));
factory.setSizeThreshold(8 * 1024 * 1024);
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> list = (List<FileItem>) upload.parseRequest(req);
for (FileItem item : list) {
if (item.isFormField()) {
} else {
String value = item.getName();
int start = value.lastIndexOf("\\");
String filename = value.substring(start + 1); String MongoDbName = req.getParameter("type");
if(MongoDbName == null){
resp.sendError(400,"bad request");
return;
}
DB db=mongo.getDB(MongoDbName);
GridFS gridFS=new GridFS(db); GridFSInputFile mongofile=gridFS.createFile(item.getInputStream());
mongofile.put("viewtimes",0);
mongofile.setContentType(item.getContentType());
mongofile.put("filename", filename);
mongofile.save(); resp.getWriter().println(mongofile);
resp.getWriter().flush();
}
}
} catch (Exception e) {
e.printStackTrace();
resp.sendError(500,"internal server error");
}
}
}
运行方法一(eclipse很简单不用介绍,linux命令行运行方法,大于8M文件通过/tmp/目录缓存):
javac -cp .:../libs/* com/speakbang/vfs/*.java -Xlint:deprecation
java -cp .:../libs/* com/speakbang/vfs/VfsServer
运行方法二(只需要VfsFileServlet.java,集成到jetty配置文件)
root:~/jetty/webapps # ls -R *
ROOT:
WEB-INF
classes
com/ciaos/vfs/VfsFileServlet.class
lib
commons-fileupload-1.3.1.jar commons-io-2.4.jar mongo-java-driver-2.11.4.jar thumbnailator-0.4.7.jar
src
com/ciaos/vfs/VfsFileServlet.java
web.xml
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>VfsServlet</servlet-name>
<servlet-class>com.ciaos.vfs.VfsFileServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>VfsServlet</servlet-name>
<url-pattern>/file</url-pattern>
</servlet-mapping>
</web-app>
cd webapps/ROOT/WEB-INF/src/
javac -cp .:../lib/*:../../../../lib/* com/ciaos/vfs/VfsFileServlet.java -Xlint:deprecation
mv com/ciaos/vfs/VfsFileServlet.class ../classes/com/ciaos/vfs/
cd ../../../../
java -jar start.jar -Xms128m -Xmx256m
(bin/jetty.sh start|restart|stop)
运行方法三(将class文件打成jar包,放到lib目录下,可以不用放置src和classes目录及源码了)
cd classes/
jar cvf vfs.jar com
cd ..
mv classes/vfs.jar lib/
rm -rf classes src
cd ../../
java -jar start.jar
注意文件不能直接操作db.fs.files.remove()删除,fs.chunks这个collection里面才是包含文件内容的,正确的删除方法使用如下脚本或者调用DELETE接口,删除完毕后用db.repairDatabase()释放磁盘空间:
var year=2014
var month=3
var day=15 use test var items = db.fs.files.find({uploadDate:{$lte:new Date(year+"/"+month+"/"+day)}})
items.forEach(function(item) {
db.fs.chunks.remove({files_id: item._id})
db.fs.files.remove({_id:item._id})
print(item._id + " deleted")
}) //运行方法: bin/mongo < tool/delete.js
//root:~/mongodb$ bin/mongo < tool/delete.js
//MongoDB shell version: 2.4.9
//connecting to: test
//switched to db test
//532259170cf2c0bcb68e1e72 deleted
//532259190cf2c0bcb68e1e76 deleted
//5322591a0cf2c0bcb68e1e7a deleted
//bye
使用方法:
上传:curl -F "action=upload" -F "Filedata=@a.png;type=image/png" -v "http://127.0.0.1:8080/file?type=test"
{ "_id" : { "$oid" : "531c5fe6744e22f4c22eeef5"} , "chunkSize" : 262144 , "length" : 1033834 , "md5" : "04bc7c0988ecc04f93cfa96f239dda99" , "filename" : "a.png" , "contentType" : null , "viewtimes" : 0 , "uploadDate" : { "$date" : "2014-03-09T12:34:46.347Z"} , "aliases" : null }
下载:curl -o /dev/null -v http://127.0.0.1:8080/file?type=test&id=531c5fe6744e22f4c22eeef5&act=preview&w=200&h=200
删除:curl -X DELETE -v "http://127.0.0.1:8080/file?type=test&id=531c5fe6744e22f4c22eeef5"
Java代码上传方法(支持多文件上传)
package com.test; import java.io.BufferedReader; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List; /**
* This utility class provides an abstraction layer for sending multipart HTTP
* POST requests to a web server.
* @author www.codejava.net
*
*/
public class MultipartUtility {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private HttpURLConnection httpConn;
private String charset;
private OutputStream outputStream;
private PrintWriter writer; /**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
* @param requestURL
* @param charset
* @throws IOException
*/
public MultipartUtility(String requestURL, String charset)
throws IOException {
this.charset = charset; // creates a unique boundary based on time stamp
boundary = "===" + System.currentTimeMillis() + "==="; URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
true);
} /**
* Adds a form field to the request
* @param name field name
* @param value field value
*/
public void addFormField(String name, String value) {
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
.append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=" + charset).append(
LINE_FEED);
writer.append(LINE_FEED);
writer.append(value).append(LINE_FEED);
writer.flush();
} /**
* Adds a upload file section to the request
* @param fieldName name attribute in <input type="file" name="..." />
* @param uploadFile a File to be uploaded
* @throws IOException
*/
public void addFilePart(String fieldName, File uploadFile)
throws IOException {
String fileName = uploadFile.getName();
writer.append("--" + boundary).append(LINE_FEED);
writer.append(
"Content-Disposition: form-data; name=\"" + fieldName
+ "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
writer.append(
"Content-Type: "
+ URLConnection.guessContentTypeFromName(fileName))
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush(); FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close(); writer.append(LINE_FEED);
writer.flush();
} /**
* Adds a header field to the request.
* @param name - name of the header field
* @param value - value of the header field
*/
public void addHeaderField(String name, String value) {
writer.append(name + ": " + value).append(LINE_FEED);
writer.flush();
} /**
* Completes the request and receives response from the server.
* @return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* @throws IOException
*/
public List<String> finish() throws IOException {
List<String> response = new ArrayList<String>(); writer.append(LINE_FEED).flush();
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.close(); // checks server's status code first
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpConn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
response.add(line);
}
reader.close();
httpConn.disconnect();
} else {
throw new IOException("Server returned non-OK status: " + status);
} return response;
} public static void main(String[] args) { String charset = "UTF-8";
File uploadFile1 = new File("c:/1.jpg");
File uploadFile2 = new File("c:/2.jpg");
String requestURL = "http://localhost:8080/file?type=test"; try {
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
/*
multipart.addHeaderField("User-Agent", "CodeJava");
multipart.addHeaderField("Test-Header", "Header-Value"); multipart.addFormField("description", "Cool Pictures");
multipart.addFormField("keywords", "Java,upload,Spring");
*/
multipart.addFilePart("fileUpload", uploadFile1);
multipart.addFilePart("fileUpload", uploadFile2); List<String> response = multipart.finish(); for (String line : response) {
System.out.println(line);
}
//output
//533e27560cf2f5c3e3d77748
//533e27560cf2f5c3e3d7774a } catch (IOException ex) {
System.err.println(ex);
}
}
}
使用jetty和mongodb实现简易网盘接口的更多相关文章
- 生活科技两相宜:(一)Win7使用微软SkyDrive网盘简易教程
今天得写一个Win7使用微软SkyDrive网盘的简易教程,主要是给我老婆看,顺便贴出来给大家共享一下:) 使用微软SkyDrive网盘有两个层次.一个是使用网页版,这个跟使用163或者QQ网盘 ...
- Layui框架+PHP打造个人简易版网盘系统
网盘系统 大家应该都会注册过致命的一些网盘~如百度云.百科介绍:网盘,又称网络U盘.网络硬盘,是由互联网公司推出的在线存储服务,服务器机房为用户划分一定的磁盘空间,为用户免费或收费提供文件的存储. ...
- 500G JAVA视频网盘分享 (Jeecg社区)
http://blog.csdn.net/zhangdaiscott/article/details/18220411 csdn 排名400多名 500 G JAVA视频网盘分享(Jeecg社区 ...
- 500G !!史上最全的JAVA全套教学视频网盘分享 (JEECG开源社区)
500 G JAVA视频网盘分享(JEECG开源社区) [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有] JEECG开源社区 ...
- 500 G JAVA视频网盘分享(JEECG开源社区)
500 G JAVA视频网盘分享(JEECG开源社区) [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有] [转载:h ...
- 500G JAVA视频网盘分享 (JEECG开源社区)
500 G JAVA视频网盘分享(JEECG开源社区) [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有] J ...
- JAVA视频网盘分享
JAVA视频网盘分享 [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有] 1.JavaScript视频教程 链接: http: ...
- 程序员需要的各种PDF格式电子书【附网盘免费下载资源地址】
程序员需要的各种PDF格式电子书[附网盘免费下载资源地址] 各位,请妥善保存,后期还会有更多更新,如果你有不同的书籍资源或者这里没有你要找的书籍,也可以直接留言,后期我们会继续更新~ Java & ...
- 分布式文件系统的比较,115网盘用了fastdfs
分布式文件系统 分布式文件系统,作为网盘的基础,应用底层文件管理.而分布式文件系统之上,用户文件的权限,用户目录管理都是由非分布式文件系统管理. 分布式文件系统需要关心的主要内容: 文件分布/数据分布 ...
随机推荐
- C++_基础_运算符重载
内容: (1)输入输出运算符重载 (2)友元类和友元函数 (3)双目运算符重载 (4)单目运算符重载 (5)不能被重载的运算符 (6)只能定义为成员形式的运算符 1.输入输出运算符重载如: int n ...
- Hive常用操作之数据导入导出
一.Hive数据导入导出 1.hive数据导出 很多时候,我们在hive中执行select语句,希望将最终的结果保存到本地文件或者保存到hdfs系统中或者保存到一个新的表中,hive提供了方便的关键词 ...
- 去掉xcode编译warning:ld: warning: directory not found for option '
tyle="margin:20px 0px 0px; font-size:14px; line-height:26px; font-family:Arial; text-align:left ...
- JQ兼容性问题
checkbox操作 1:设置为选中状态 $(this).prop("checked", true); 2:判断是否选中 $(this).is(":check ...
- ASP中 Request.Form中文乱码的解决方法
分享下解决方法直接用request.Form()获取的是所有数据所以会有乱码(具体原因不祥) 用 VBScript code Foreach obj in Request.Form Response. ...
- 制作OB图的时候,OB玩家进入后就退出的问题
开始怀疑是 OB玩家没有建筑 所以强行退出了,有朋友说那是因为有无效的触发造成的 我没有测试过 最后解决是给OB玩家在地图中加上建筑 更新 最后测试,把OB玩家放到一个组里 开局KILL掉这个组的建筑 ...
- 【转】linux Centos 6.5 安装桌面环境GNOME
在某种场合之下,我们使用的Linux还是要选择安装桌面环境的,所以在这里介绍一下如何给没有安装桌面环境的系统安装桌面环境. 以Centos 6.5 为例演示一下如何安装桌面环境. 一.首先查看系统的运 ...
- RHEL6.4 postfix+dovecot搭建邮件服务器
实验需求:为公司搭建一台能够收信和发信的邮件服务器(192.168.100.1),为员工提供服务,公司域名为jinjianjun.com. 一.修改DNS服务器(192.168.100.2)上mx邮件 ...
- 自定义TWebBrowser浏览器控制遇到的一些问题
最近工作需要,要将TWebBrowser样式改头换面,包括菜单,滚动条等,都要换掉. 由于滚动条已经屏蔽掉,所以关于页面滚动等,全部都需要自己写代码来模拟了.模拟的过程中发现获得页面的客户区大小Cli ...
- mysqldump 利用rr隔离实现一致性备份
mysqldump -p -S /data/mysqldata1/sock/mysql.sock --single-transaction --master-data=2 --database db1 ...