摘要:AndServer是一个基于 Java 的 Android 小型服务器库,可用于在 Android 应用中轻松创建和管理 HTTP 服务器,基于Android平台的Web Server和Web Framework,基于编译时注解提供了类似SpringMVC的注解和功能。在项目实践中,您可以使用 AndServer 来创建一个本地的 HTTP 服务器,用于与应用内的其他组件、模块或远程客户端进行通信,比如实现调式日志的导出、上传;通过接口回调的方式实现修改APP缓存的配置以及信息;修改硬件属性内容等;他可支持三种部署模式:静态html网站部署;动态http api部署;反向代理服务器。
引用于网络:
AndServer框架的作者是严振杰,关于该框架的使用方法,他的博客有对应的文章。不过,该文章有些老旧了,因为上边给出的github项目与该文章所讲的并不匹配。即使是下载了sample,菜鸟也不知道如何实现文件的下载功能,因为sample里面只有文件上传的例子。为此,本人阅读了其他博主相关的文章,自己实现了文件上传、下载的功能。
AndServer框架可以把安卓手机变身为一台Web服务器,其他设备只需要和该手机连接同一个网络,在浏览器输入相应的地址,就可以访问、操作该手机(Web服务器)上的资源。
本篇文章的最后会免费给出整个项目的源码以及成品软件。
项目源代码以及项目接口文档地址:
- 源码地址: https://github.com/yanzhenjie/AndServer/
- 文档地址: https://yanzhenjie.github.io/AndServer/
- 旧版文档:yanzhenjie.github.io/AndServer/1…
一、部署网络服务器
Server server = AndServer.webServer(context)
.port(8080)
.timeout(10, TimeUnit.SECONDS)
.build();
// startup the server.
server.startup();
...
// shutdown the server.
server.shutdown();
使用SpringMVC进行接口的编写:
@RestController
@RequestMapping(path = "/user")
public class UserController {
@PostMapping("/login")
public String login(@RequestParam("account") String account,
@RequestParam("password") String password) {
...
return "Successful.";
}
@GetMapping(path = "/{userId}")
public User info(@PathVariable("userId") String userId,
@QueryParam("fields") String fields) {
User user = findUserById(userId, fields);
...
return user;
}
@PutMapping(path = "/{userId}")
public void modify(@PathVariable("userId") String userId
@RequestParam("age") int age) {
...
}
}
三、示例关键代码:
1、说明
a、AS版本:开发此项目本人使用的Android Studio版本是4.1.1
b、添加依赖:本人使用的AndServer版本为1.1.3,需要在Module的build.gradle文件里面添加如下依赖:
implementation 'com.yanzhenjie:andserver:1.1.3'
c、前端用到的框架
本篇文章就不给出前端的代码了,因为用到的都是最基础的知识,前端只是单纯地展示一下后端返回的数据而已。前端用到的框架主要有Bootstrap、Jquery。
2、生成Server对象代码
Server.Builder builder = AndServer.serverBuilder();
builder.inetAddress(NetUtils.getLocalIPAddress());
builder.port(port);
WebSite webSite=new AssetsWebsite(getAssets(),"web");//网站是放在assets/web目录下的
builder.website(webSite);//部署网站
builder.registerHandler("/fileDownload",new FileDownloadHandler());
builder.registerHandler("/fileUpload",new FileUploadHandler());
builder.registerHandler("/fileList",new FileListHandler());
builder.registerHandler("/fileDel",new FileDeleteHandler());
builder.listener(new Server.ServerListener() {
@Override
public void onStarted() {
LogUtils.logD(TAG,"服务器启动完成……");
hostAddress = mServer.getInetAddress().getHostAddress();
System.out.println("主机地址是:"+hostAddress);
MybroadcastReceiver.onServerStart(CoreService.this,hostAddress);
}
@Override
public void onStopped() {
LogUtils.logD(TAG,"服务器已停止……");
MybroadcastReceiver.onServerStop(CoreService.this);
}
@Override
public void onError(Exception e) {
LogUtils.logD(TAG,"服务器发生错误,错误信息:"+e.getMessage());
MybroadcastReceiver.onServerError(CoreService.this,e.getMessage());
}
});
mServer= builder.build();//构建出Server对象
3、文件上传的代码
public class FileUploadHandler implements RequestHandler {
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
File file=new File(FileUtils.fileDirectory);//临时文件的存放目录
FileItemFactory fileItemFactory = new DiskFileItemFactory(10*1024 * 1024, file);//第一个参数是缓存的大小
HttpFileUpload httpFileUpload=new HttpFileUpload(fileItemFactory);
String name=null;
boolean isFinished=false;
String errMsg="";
try {
List<FileItem> fileItemList = httpFileUpload.parseRequest(request);
for (FileItem fileItem : fileItemList) {
if(fileItem.isFormField()){//普通参数
name = fileItem.getName();
String string = fileItem.getString();
System.out.println("上送的参数名:"+name+",参数值:"+string);
}else{//文件
String fieldName = fileItem.getFieldName();
long size = fileItem.getSize();//文件大小
String contentType = fileItem.getContentType();
if(name==null||name.length()<2){
name=fileItem.getName();
}
System.out.println("上传的参数,文件大小:"+size+"字节,文件名:"+name+",类型:"+contentType+",表单名字:"+fieldName);
File uploadFile=new File(file,name);
fileItem.write(uploadFile);//将文件写入存储卡中
isFinished=true;
}
}
} catch (Exception e) {
e.printStackTrace();
errMsg=e.getMessage();
}
if(isFinished){
response.setEntity(new StringEntity("文件上传完成!","utf-8"));
}else {
response.setEntity(new StringEntity("文件上传失败,服务器未接收到任何文件!错误信息:"+errMsg,"utf-8"));
}
response.setHeader("Content-Type","text/html;charset=utf-8");
}
}
4、文件下载的代码
public class FileListHandler implements RequestHandler {
@RequestMapping(method={RequestMethod.GET})
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
/*String contentFromBody = HttpRequestParser.getContentFromBody(request);//从请求体中获取数据
System.out.println("请求体:"+contentFromBody);
String substring = contentFromBody.substring(5, contentFromBody.length());
String decode= URLDecoder.decode(substring, "utf-8"); */
String uri = request.getRequestLine().getUri();
String fileName= uri.substring(10, uri.length());
String decode = URLDecoder.decode(fileName, "utf-8");
System.out.println("请求的URI是:"+uri);
System.out.println("文件名是:"+fileName);
System.out.println("解码后的文件名:"+decode);
FileEntity fileEntity=new FileEntity(new File(FileUtils.fileDirectory+"/"+decode));
response.setHeader("Content-Disposition", "attachment;filename="+decode);//不设置这个就没有下载的效果,举例:如果是txt文件,浏览器就会直接展示文字,而不是下载
response.setEntity(fileEntity);
}
}
四、截图
1、浏览器截图
2、手机(web服务器)截图
附录:
- blog.csdn.net/Deep_rooted… 利用AndServer框架把安卓手机变成Web服务器实现局域网文件上传、下载功能