This is an automated email from the ASF dual-hosted git repository.
zhangzicheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 10d466cfc [ISSUE #3740] add websocket upload file example and
integrated test (#3798)
10d466cfc is described below
commit 10d466cfc5f1bd0e37d3d11e3e5b070528a775e1
Author: Haitao Ma(jimmy) <[email protected]>
AuthorDate: Fri Aug 5 00:23:12 2022 +0800
[ISSUE #3740] add websocket upload file example and integrated test (#3798)
* feat:add websocket upload file example and integrated test
* feat:fix
* feat:fix file with checkstyle problem
* feat:fix checkstyle problem
* feat:fix websocket-integrated-test
* formate
* feat:format
Co-authored-by: mahaitao617 <[email protected]>
---
.../examples/websocket/service/SaveFile.java | 25 +++++++
.../examples/websocket/service/SaveFileImpl.java | 50 +++++++++++++
.../examples/websocket/ws/UpLoadController.java | 82 ++++++++++++++++++++++
.../websocket/config/WsSessionManager.java | 4 ++
.../websocket/controller/TestHttpController.java | 22 ++++++
.../websocket/config/WebSocketConfiguration.java | 11 +++
.../websocket/handler/UploadFileHandler.java | 40 +++++++++++
.../test/websocket/UploadControllerTest.java | 65 +++++++++++++++++
8 files changed, 299 insertions(+)
diff --git
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/service/SaveFile.java
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/service/SaveFile.java
new file mode 100644
index 000000000..207863c33
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/service/SaveFile.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.examples.websocket.service;
+
+import java.util.Map;
+
+public interface SaveFile {
+
+ boolean saveFileFromBytes(byte[] b, Map<String, Object> map);
+}
diff --git
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/service/SaveFileImpl.java
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/service/SaveFileImpl.java
new file mode 100644
index 000000000..559b7db72
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/service/SaveFileImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.examples.websocket.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Map;
+
+@Service
+public class SaveFileImpl implements SaveFile {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(SaveFileImpl.class);
+
+ @Override
+ public boolean saveFileFromBytes(final byte[] b, final Map<String, Object>
map) {
+ //从map中获取file对象
+ File file = (File) map.get("file");
+ //判断路径是否存在,不存在就创建
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+
+ try (FileOutputStream fstream = new FileOutputStream(file, true)) {
+ fstream.write(b);
+ } catch (Exception e) {
+ LOG.error("saveFileFromBytes error", e);
+ return false;
+ }
+ return true;
+ }
+}
diff --git
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/ws/UpLoadController.java
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/ws/UpLoadController.java
new file mode 100644
index 000000000..8258808b4
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/src/main/java/org/apache/shenyu/examples/websocket/ws/UpLoadController.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.examples.websocket.ws;
+
+import
org.apache.shenyu.client.spring.websocket.annotation.ShenyuSpringWebSocketClient;
+import org.apache.shenyu.examples.websocket.service.SaveFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+import javax.websocket.OnClose;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.ServerEndpoint;
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+
+@ShenyuSpringWebSocketClient("/upload")
+@ServerEndpoint("/upload")
+@Controller
+public class UpLoadController {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(UpLoadController.class);
+
+ @Autowired
+ private SaveFile saveFile;
+
+ @OnOpen
+ public void onOpen(final Session session) {
+ LOG.info("connect successful");
+ }
+
+ /**
+ * connect close.
+ *
+ * @param session used for verify
+ */
+ @OnClose
+ public void onClose(final Session session) {
+ LOG.info("connect1 closed");
+ }
+
+ @OnMessage
+ public void onMessage(final String message, final Session session) {
+ try {
+ session.getBasicRemote().sendText("ok");
+ } catch (IOException e) {
+ LOG.error("UpLoadController onMessage error", e);
+ }
+ }
+
+ @OnMessage
+ public void onMessage(final byte[] message, final Session session) {
+ File file = (File) session.getUserProperties().get("file");
+ try {
+ ConcurrentHashMap map = new ConcurrentHashMap<>();
+ map.put("file", file);
+ saveFile.saveFileFromBytes(message, map);
+ session.getBasicRemote().sendText("ok");
+ } catch (Exception e) {
+ LOG.error("UpLoadController onMessage", e);
+ }
+ }
+}
diff --git
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-native-websocket/src/main/java/org/apache/shenyu/examples/websocket/config/WsSessionManager.java
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-native-websocket/src/main/java/org/apache/shenyu/examples/websocket/config/WsSessionManager.java
index eda516312..6392fe80a 100644
---
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-native-websocket/src/main/java/org/apache/shenyu/examples/websocket/config/WsSessionManager.java
+++
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-native-websocket/src/main/java/org/apache/shenyu/examples/websocket/config/WsSessionManager.java
@@ -18,6 +18,8 @@
package org.apache.shenyu.examples.websocket.config;
import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
@@ -28,6 +30,8 @@ import java.util.concurrent.ConcurrentHashMap;
*/
@Slf4j
public class WsSessionManager {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(WsSessionManager.class);
/**
* save the connection session.
*/
diff --git
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-native-websocket/src/main/java/org/apache/shenyu/examples/websocket/controller/TestHttpController.java
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-native-websocket/src/main/java/org/apache/shenyu/examples/websocket/controller/TestHttpController.java
index 510cb1668..870cd6bc5 100644
---
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-native-websocket/src/main/java/org/apache/shenyu/examples/websocket/controller/TestHttpController.java
+++
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-native-websocket/src/main/java/org/apache/shenyu/examples/websocket/controller/TestHttpController.java
@@ -21,8 +21,12 @@ import
org.apache.shenyu.client.springmvc.annotation.ShenyuSpringMvcClient;
import org.apache.shenyu.examples.common.aop.Log;
import org.apache.shenyu.examples.websocket.config.WsSessionManager;
import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
@@ -47,4 +51,22 @@ public class TestHttpController {
webSocketSession.sendMessage(new TextMessage(msg));
return "Message sent successfully";
}
+
+ @PostMapping(value = "/upload")
+ @Log
+ public @ResponseBody
+ Object file(String token, @RequestParam("file") final MultipartFile file) {
+ try {
+ WebSocketSession webSocketSession = WsSessionManager.get(token);
+ if (webSocketSession == null) {
+ return "User login has expired";
+ }
+ if (file.getOriginalFilename().endsWith(".bin")) {
+ webSocketSession.sendMessage(new
BinaryMessage(file.getBytes()));
+ }
+ } catch (Exception e) {
+
+ }
+ return "ok";
+ }
}
\ No newline at end of file
diff --git
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-reactive-websocket/src/main/java/org/apache/shenyu/examples/websocket/config/WebSocketConfiguration.java
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-reactive-websocket/src/main/java/org/apache/shenyu/examples/websocket/config/WebSocketConfiguration.java
index 7084d095a..d19387385 100644
---
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-reactive-websocket/src/main/java/org/apache/shenyu/examples/websocket/config/WebSocketConfiguration.java
+++
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-reactive-websocket/src/main/java/org/apache/shenyu/examples/websocket/config/WebSocketConfiguration.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.examples.websocket.config;
import
org.apache.shenyu.client.spring.websocket.annotation.ShenyuSpringWebSocketClient;
import org.apache.shenyu.examples.websocket.handler.EchoHandler;
+import org.apache.shenyu.examples.websocket.handler.UploadFileHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
@@ -53,6 +54,16 @@ public class WebSocketConfiguration {
return mapping;
}
+ @Bean
+ public HandlerMapping websocketFileMapping(final UploadFileHandler
uploadFileHandler){
+ final Map<String, WebSocketHandler> map = new HashMap<>(1);
+ map.put("/websocket/upload", uploadFileHandler);
+ final SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
+ mapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
+ mapping.setUrlMap(map);
+ return mapping;
+ }
+
/**
* Handler adapter web socket handler adapter.
*
diff --git
a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-reactive-websocket/src/main/java/org/apache/shenyu/examples/websocket/handler/UploadFileHandler.java
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-reactive-websocket/src/main/java/org/apache/shenyu/examples/websocket/handler/UploadFileHandler.java
new file mode 100644
index 000000000..55c240e22
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-reactive-websocket/src/main/java/org/apache/shenyu/examples/websocket/handler/UploadFileHandler.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.examples.websocket.handler;
+
+import org.apache.shenyu.examples.common.aop.Log;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.socket.WebSocketHandler;
+import org.springframework.web.reactive.socket.WebSocketSession;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class UploadFileHandler implements WebSocketHandler {
+
+
+ @Override
+ @NonNull
+ @Log
+ public Mono<Void> handle(final WebSocketSession session) {
+ return session.send(
+ session.receive()
+ .map(msg ->
session.binaryMessage(msg.getNativeMessage())));
+ }
+}
diff --git
a/shenyu-integrated-test/shenyu-integrated-test-websocket/src/test/java/org/apache/shenyu/integrated/test/websocket/UploadControllerTest.java
b/shenyu-integrated-test/shenyu-integrated-test-websocket/src/test/java/org/apache/shenyu/integrated/test/websocket/UploadControllerTest.java
new file mode 100644
index 000000000..9250230d5
--- /dev/null
+++
b/shenyu-integrated-test/shenyu-integrated-test-websocket/src/test/java/org/apache/shenyu/integrated/test/websocket/UploadControllerTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.integrated.test.websocket;
+
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.RequestBody;
+import org.apache.shenyu.integratedtest.common.AbstractPluginDataInit;
+import org.apache.shenyu.integratedtest.common.helper.HttpHelper;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static org.junit.Assert.assertEquals;
+
+public class UploadControllerTest extends AbstractPluginDataInit {
+
+ private static final String FILE_PATH = "1.bin";
+
+ @BeforeAll
+ public static void setup() throws IOException {
+ Path pathOne = Paths.get(FILE_PATH);
+ if (!Files.exists(pathOne)) {
+ Files.createFile(pathOne);
+ }
+ BufferedWriter bufferedWriterOne = Files.newBufferedWriter(pathOne);
+ bufferedWriterOne.write("111");
+ bufferedWriterOne.flush();
+ bufferedWriterOne.close();
+ }
+
+ @Test
+ public void testWebsocketUpLoad() throws IOException {
+ File fileOne = new File(FILE_PATH);
+ RequestBody fileBodyOne =
RequestBody.create(MediaType.parse("multipart/form-data"), fileOne);
+ MultipartBody requestBody = new MultipartBody.Builder()
+ .setType(MultipartBody.FORM)
+ .addFormDataPart("file", FILE_PATH, fileBodyOne)
+ .build();
+ final String response =
HttpHelper.INSTANCE.postGateway("/ws-native/ws/upload", requestBody,
String.class);
+ assertEquals(response, "ok");
+ }
+
+}