├── .gitignore
├── java-upload
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── devsai
│ │ │ ├── ctrl
│ │ │ ├── MainCtrl.class
│ │ │ ├── MyHiddenFileFilter.java
│ │ │ ├── CommonResult.java
│ │ │ ├── MainCtrl.java
│ │ │ └── UploadController.java
│ │ │ ├── test
│ │ │ ├── MyMd5.java
│ │ │ └── MyProtoBuf.java
│ │ │ ├── ws
│ │ │ ├── MyWSThread.java
│ │ │ ├── EventServlet.java
│ │ │ ├── EventServer.java
│ │ │ ├── MyServlet.java
│ │ │ ├── EventSocket.java
│ │ │ └── StockServiceWebSocket.java
│ │ │ ├── view
│ │ │ ├── ViewInitView.java
│ │ │ └── MultiUrlViewResolver.java
│ │ │ ├── filter
│ │ │ └── MyFilter.java
│ │ │ ├── model
│ │ │ ├── UploadFile.java
│ │ │ └── UploadMsg.java
│ │ │ └── service
│ │ │ └── UploadService.java
│ │ └── webapp
│ │ ├── static
│ │ ├── proto
│ │ │ └── upload.proto
│ │ ├── index.css
│ │ ├── index.html
│ │ ├── uploadMethod
│ │ │ ├── formUpload.html
│ │ │ ├── iframeUpload.html
│ │ │ ├── chunkUpload.html
│ │ │ ├── wsUpload.html
│ │ │ └── ajaxUpload.html
│ │ ├── fileList.html
│ │ ├── js
│ │ │ └── chunk.js
│ │ └── demo.html
│ │ └── WEB-INF
│ │ ├── jsp
│ │ └── hello.jsp
│ │ ├── log4j.xml
│ │ ├── web.xml
│ │ ├── applicationContext.xml
│ │ └── UploadWeb-servlet.xml
├── uploadserver.iml
└── pom.xml
├── node-upload
├── static
│ ├── proto
│ │ └── upload.proto
│ ├── style.css
│ ├── index.html
│ ├── js
│ │ └── chunk.js
│ └── uploadMethod
│ │ ├── corsUpload.html
│ │ ├── iframeUpload.html
│ │ ├── chunkUpload.html
│ │ ├── ajaxUpload.html
│ │ └── wsUpload.html
├── package.json
├── ws_server.js
└── server.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | **/node_module
2 | node-upload/node_modules
3 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/ctrl/MainCtrl.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiangsai/web-upload-demo/HEAD/java-upload/src/main/java/com/devsai/ctrl/MainCtrl.class
--------------------------------------------------------------------------------
/node-upload/static/proto/upload.proto:
--------------------------------------------------------------------------------
1 | message Upload {
2 | required string filename = 1;
3 | required int32 currchunk = 2;
4 | required int32 chunks = 3;
5 | required int32 uid = 4;
6 | required bytes upload_file = 5;
7 | }
8 |
--------------------------------------------------------------------------------
/java-upload/src/main/webapp/static/proto/upload.proto:
--------------------------------------------------------------------------------
1 | message Upload {
2 | required string filename = 1;
3 | required int32 currchunk = 2;
4 | required int32 chunks = 3;
5 | required int32 uid = 4;
6 | required bytes upload_file = 5;
7 | }
8 |
--------------------------------------------------------------------------------
/java-upload/src/main/webapp/WEB-INF/jsp/hello.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html; charset=UTF-8" %>
2 |
3 |
4 | Hello World
5 |
6 |
7 | ${message}
8 | 当前时间:${currdate}
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/test/MyMd5.java:
--------------------------------------------------------------------------------
1 | package com.devsai.test;
2 |
3 | import sun.security.provider.MD5;
4 |
5 | /**
6 | * Created by huangxiangsai on 16/6/17.
7 | */
8 | public class MyMd5 {
9 |
10 | public static void main(String[] argv){
11 | MD5 md5 = new MD5();
12 |
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/ctrl/MyHiddenFileFilter.java:
--------------------------------------------------------------------------------
1 | package com.devsai.ctrl;
2 |
3 | import org.apache.commons.io.filefilter.AbstractFileFilter;
4 | import org.apache.commons.io.filefilter.HiddenFileFilter;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * Created by huangxiangsai on 16/6/30.
10 | */
11 | public class MyHiddenFileFilter extends HiddenFileFilter implements Serializable {
12 | }
13 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/ws/MyWSThread.java:
--------------------------------------------------------------------------------
1 | //package com.devsai.ws;
2 | //
3 | ///**
4 | // * Created by huangxiangsai on 16/7/6.
5 | // */
6 | //public class MyWSThread implements Runnable{
7 | //
8 | // public MyWSThread(){
9 | // EventServer es= new EventServer();
10 | // es.createServer();
11 | // System.out.println("create websocket server........");
12 | // }
13 | // public void run() {
14 | //
15 | // }
16 | //}
17 |
--------------------------------------------------------------------------------
/node-upload/static/style.css:
--------------------------------------------------------------------------------
1 | iframe{
2 | display:block;
3 | }
4 |
5 |
6 | .chooseFile{
7 | position: relative;
8 | background-color: white;
9 | overflow: hidden;
10 | }
11 |
12 | .chooseFile input{
13 | width: 161px;
14 | opacity: 0;
15 | position: absolute;
16 | display: inline-block;
17 | float: left;
18 | left: -80px;
19 | top: 0;
20 | }
21 |
22 | .mgl-30{
23 | margin-left : 30px;
24 | }
25 |
26 |
27 | .list-group.js-list{
28 | display:inline-block;
29 | width:49%;
30 | }
--------------------------------------------------------------------------------
/java-upload/src/main/webapp/static/index.css:
--------------------------------------------------------------------------------
1 | iframe{
2 | display:block;
3 | }
4 |
5 |
6 | .chooseFile{
7 | position: relative;
8 | background-color: white;
9 | overflow: hidden;
10 | }
11 |
12 | .chooseFile input{
13 | width: 161px;
14 | opacity: 0;
15 | position: absolute;
16 | display: inline-block;
17 | float: left;
18 | left: -80px;
19 | top: 0;
20 | }
21 |
22 | .mgl-30{
23 | margin-left : 30px;
24 | }
25 |
26 |
27 | .list-group.js-list{
28 | display:inline-block;
29 | width:49%;
30 | }
--------------------------------------------------------------------------------
/node-upload/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-upload-demo",
3 | "version": "1.0.0",
4 | "description": "web uplaod file demo for node",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "node server.js & node ws_server.js"
8 | },
9 | "keywords": [
10 | "upload",
11 | "ajax"
12 | ],
13 | "author": "SAI",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "content-type-mime": "^1.0.1",
17 | "formidable": "^1.0.17",
18 | "json-stable-stringify": "^1.0.1",
19 | "koa": "^1.2.4",
20 | "koa-better-body": "^3.0.2",
21 | "koa-cors": "^0.0.16",
22 | "koa-router": "^5.4.0",
23 | "koa-static": "^2.0.0",
24 | "protobufjs": "^5.0.1",
25 | "ws": "^1.1.1"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/view/ViewInitView.java:
--------------------------------------------------------------------------------
1 | package com.devsai.view;
2 |
3 | import org.springframework.web.servlet.view.AbstractTemplateView;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.util.Map;
8 |
9 | /**
10 | * Created by huangxiangsai on 16/6/21.
11 | */
12 | public class ViewInitView extends AbstractTemplateView {
13 | @Override
14 | protected void renderMergedTemplateModel(Map map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
15 |
16 | }
17 |
18 | protected void exposeHelpers(Map model,
19 | HttpServletRequest request) throws Exception {
20 | model.put("base", request.getContextPath());
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/ws/EventServlet.java:
--------------------------------------------------------------------------------
1 | package com.devsai.ws;
2 |
3 | /**
4 | * Created by huangxiangsai on 16/7/1.
5 | */
6 | import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
7 | import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
8 |
9 | @SuppressWarnings("serial")
10 | public class EventServlet extends WebSocketServlet
11 | {
12 | private static final Integer MAX_MESSAGE_SIZE = 920092544;
13 |
14 | @Override
15 | public void configure(WebSocketServletFactory factory)
16 | {
17 | factory.getPolicy().setMaxBinaryMessageSize(MAX_MESSAGE_SIZE);
18 | factory.getPolicy().setMaxBinaryMessageBufferSize(MAX_MESSAGE_SIZE);
19 | factory.getPolicy().setMaxTextMessageBufferSize(MAX_MESSAGE_SIZE);
20 | factory.getPolicy().setMaxTextMessageSize(MAX_MESSAGE_SIZE);
21 | factory.register(EventSocket.class);
22 | }
23 | }
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/filter/MyFilter.java:
--------------------------------------------------------------------------------
1 | package com.devsai.filter;
2 |
3 | import org.springframework.web.filter.OncePerRequestFilter;
4 |
5 | import javax.servlet.FilterChain;
6 | import javax.servlet.ServletException;
7 | import javax.servlet.http.HttpServletRequest;
8 | import javax.servlet.http.HttpServletResponse;
9 | import java.io.IOException;
10 |
11 | /**
12 | * Created by huangxiangsai on 16/11/8.
13 | */
14 | public class MyFilter extends OncePerRequestFilter{
15 | @Override
16 | protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
17 |
18 | // if (httpServletRequest.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(httpServletRequest.getMethod())) {
19 | httpServletResponse.addHeader("Access-Control-Allow-Origin","*");
20 |
21 | // }
22 | System.out.println("myFilter...");
23 | filterChain.doFilter(httpServletRequest,httpServletResponse);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # web上传
2 |
3 | web上传在网站开发中经常会用到,web上传在很早前就有,可通过表单提交实现上传,
4 |
5 | 后来flash插件大举进入网站,使用flash实现,可以实现强大的上传功能
6 |
7 | 在后来有了HTML5,ajax支持了上传文件,不需要flash也能实现强大的上传。
8 |
9 | 本栗子只做了简单的上传Demo,想了解web上传相关可以查看[聊聊web上传](http://huangxiangsai.github.io/2016/11/08/talk-web-upload/)
10 |
11 | ## 提供了两个版本的上传服务
12 |
13 | node版web上传 、 java版web上传
14 |
15 | ## 如何使用demo
16 |
17 | ### node版web上传
18 |
19 | * 进入node-upload目录
20 | * 使用npm i 安装依赖(当然已经配置了cnpm,也可以使用cnpm)
21 | * 执行命令npm start启动服务(将会启动两个服务:web服务,websocket服务)
22 | * 打开浏览器访问静态文件127.0.0.1:8083/index.html
23 |
24 | ### java版web上传
25 |
26 | * 导入到IDE
27 | * 加载maven依赖
28 | * 启动jetty(当然也可以其他web服务)
29 | * 打开浏览器访问静态文件127.0.0.1:8888/static/index.html
30 | * 执行com.devsai.ws.EventServer.java的main方法启动websocket服务
31 |
32 |
33 | ### 跨域资源共享(用于测试上传跨域的简单请求及预检测请求)
34 |
35 | 此部分内容为你所不知道的跨域资源共享(CORS)的DEMO
36 |
37 | 以node版为例,
38 | 在node版服务端中添加了跨域资源共享的支持,并添加了**corsUpload**路由接口
39 |
40 | 通过访问`http://127.0.0.1:8083/index.html` >> 跨域上传 进入页面
41 |
42 | html页面路径为**/static/uploadMethod/corsUpload.html**
43 |
44 | 打开控制台,上传文件,观察上传的请求情况,
45 |
46 | 也可修改html页面中JS,根据博文中所说的,进行修改,再次上传,观察上传请求情况。
47 |
48 |
--------------------------------------------------------------------------------
/java-upload/src/main/webapp/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
Web Upload File 详解
12 |
13 |
14 |
web上传的几种方法
15 |
27 |
28 |
29 |
30 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/model/UploadFile.java:
--------------------------------------------------------------------------------
1 | package com.devsai.model;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * Created by huangxiangsai on 16/5/22.
7 | */
8 | public class UploadFile implements Serializable{
9 |
10 |
11 |
12 | private String name;
13 |
14 | private Long size;
15 |
16 | private String type;
17 |
18 | private String path;
19 |
20 | private byte[] content;
21 |
22 | public String getName() {
23 | return name;
24 | }
25 |
26 | public void setName(String name) {
27 | this.name = name;
28 | }
29 |
30 | public Long getSize() {
31 | return size;
32 | }
33 |
34 | public void setSize(Long size) {
35 | this.size = size;
36 | }
37 |
38 | public String getType() {
39 | return type;
40 | }
41 |
42 | public void setType(String type) {
43 | this.type = type;
44 | }
45 |
46 | public String getPath() {
47 | return path;
48 | }
49 |
50 | public void setPath(String path) {
51 | this.path = path;
52 | }
53 |
54 | public byte[] getContent() {
55 | return content;
56 | }
57 |
58 | public void setContent(byte[] content) {
59 | this.content = content;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/node-upload/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
Web Upload File 详解
12 |
13 |
14 |
web上传的几种方法
15 |
28 |
29 |
30 |
31 |
32 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/test/MyProtoBuf.java:
--------------------------------------------------------------------------------
1 | package com.devsai.test;
2 |
3 | import com.devsai.model.UploadMsg;
4 | import com.google.protobuf.ByteString;
5 |
6 | /**
7 | * Created by huangxiangsai on 16/7/8.
8 | */
9 | public class MyProtoBuf {
10 |
11 | public static void main(String[] args) {
12 |
13 | // creating the cat
14 | UploadMsg.Upload uploadMsg= UploadMsg.Upload.newBuilder()
15 | .setFilename("")
16 | .setChunks(10)
17 | .setUid(1)
18 | .setCurrchunk(1)
19 | // .setFilenameBytes(new byte[4])
20 | .build();
21 |
22 | ByteString uploadFile = uploadMsg.getUploadFile();
23 | byte[] content = new byte[uploadFile.size()];
24 | uploadFile.copyTo(content,0);
25 |
26 |
27 | // try {
28 | // // write
29 | // FileOutputStream output = new FileOutputStream("cat.ser");
30 | // pusheen.writeTo(output);
31 | // output.close();
32 | //
33 | // // read
34 | // Cat catFromFile = Cat.parseFrom(new FileInputStream("cat.ser"));
35 | // System.out.println(catFromFile);
36 | //
37 | // } catch (IOException e) {
38 | // e.printStackTrace();
39 | // }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/ws/EventServer.java:
--------------------------------------------------------------------------------
1 | package com.devsai.ws;
2 |
3 | /**
4 | * Created by huangxiangsai on 16/7/1.
5 | */
6 | import org.eclipse.jetty.server.Server;
7 | import org.eclipse.jetty.server.ServerConnector;
8 | import org.eclipse.jetty.servlet.ServletContextHandler;
9 | import org.eclipse.jetty.servlet.ServletHolder;
10 |
11 | public class EventServer
12 | {
13 |
14 | private Server server;
15 |
16 |
17 | public static void main(String[] args)
18 | {
19 | Server server = new Server();
20 | ServerConnector connector = new ServerConnector(server);
21 | connector.setPort(8081);
22 | server.addConnector(connector);
23 |
24 | // Setup the basic application "context" for this application at "/"
25 | // This is also known as the handler tree (in jetty speak)
26 | ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
27 | context.setContextPath("/");
28 | server.setHandler(context);
29 | // Add a websocket to a specific path spec
30 | ServletHolder holderEvents = new ServletHolder("ws-events", EventServlet.class);
31 |
32 | context.addServlet(holderEvents, "/upload/*");
33 |
34 | // holderEvents.
35 |
36 | try
37 | {
38 | server.start();
39 | server.dump(System.err);
40 | server.join();
41 | }
42 | catch (Throwable t)
43 | {
44 | t.printStackTrace(System.err);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/ws/MyServlet.java:
--------------------------------------------------------------------------------
1 | package com.devsai.ws;
2 |
3 | /**
4 | * Created by huangxiangsai on 16/7/6.
5 | */
6 | import java.io.IOException;
7 | import javax.servlet.ServletException;
8 | import javax.servlet.http.HttpServletRequest;
9 | import javax.servlet.http.HttpServletResponse;
10 | import javax.servlet.annotation.WebServlet;
11 | import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
12 | import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
13 |
14 | @WebServlet(name = "WebSocket Servlet", urlPatterns = { "/wsexample" })
15 | public class MyServlet extends WebSocketServlet {
16 |
17 | private static final Integer MAX_MESSAGE_SIZE = 10000000;
18 |
19 | @Override
20 | public void doGet(HttpServletRequest request,
21 | HttpServletResponse response) throws ServletException, IOException {
22 | response.getWriter().println("HTTP GET method not implemented.");
23 | }
24 |
25 | @Override
26 | public void configure(WebSocketServletFactory factory) {
27 | factory.getPolicy().setIdleTimeout(10000);
28 | factory.getPolicy().setMaxBinaryMessageSize(MAX_MESSAGE_SIZE);
29 | factory.getPolicy().setMaxBinaryMessageBufferSize(MAX_MESSAGE_SIZE);
30 | factory.getPolicy().setInputBufferSize(MAX_MESSAGE_SIZE);
31 | factory.getPolicy().setMaxTextMessageBufferSize(MAX_MESSAGE_SIZE);
32 | factory.getPolicy().setMaxTextMessageSize(MAX_MESSAGE_SIZE);
33 | factory.register(StockServiceWebSocket.class);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/java-upload/src/main/java/com/devsai/ctrl/CommonResult.java:
--------------------------------------------------------------------------------
1 | package com.devsai.ctrl;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 |
6 | /**
7 | * Created by huangxiangsai on 16/5/21.
8 | */
9 | public class CommonResult {
10 |
11 | private int code ;
12 | private String message;
13 | private List