NotesUESTC/Android开发笔记/Smb开发笔记.md

123 lines
3.6 KiB
Markdown
Raw Permalink Normal View History

2024-03-27 11:19:08 +08:00
## Android Smb开发笔记
### 一、SMB的基本操作
Android的SMB开发会用到jcifs这个库。这个库提供了SMB的底层操作功能。
根据URI打开一个SMB。
```java
// 指定SMB的路径
String uri = "smb://administrator:351002@192.168.31.52/H/琅琊榜 全54集 1080P/";
// 网络的相关操作必须通过新线程的方式启动否则会触发Android的错误
new Thread(new Runnable() {
@Override
public void run() {
try {
// 根据uri打开SmbFile
SmbFile smbFile = new SmbFile(uri);
String fileName = smbFile.getName();
Log.d("Test", fileName);
// 控制台打印SMB路径下的文件
try{
String[] FileList = smbFile.list();
for (String s : FileList) {
Log.d("Test", s);
}
}catch (SmbException e){
e.printStackTrace();
}
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}).start();
```
### 二、SMB转HTTP
当我们把SMB的Uri提供给播放器后播放器会请求GET视频。对于一个完整的视频Http的请求如下所示。
如果我们在解析请求头的时候没有收到请求的范围信息,那么默认就是返回全部的内容。
```shell
GET /smb/192.168.31.52/I/XXX.mp4 HTTP/1.1
User-Agent: ExoPlayerTime/1.0 (Linux;Android 12) ExoPlayerLib/2.7.1
Accept-Encoding:identity
Host: 127.0.0.1:2222
Connection: Keep-Alive
```
当我们拖动进度条的时候此时视频不是从0开始播放所以视频播放器会请求包含Range的信息
```Shell
GET /smb/192.168.31.52/I/XXX.mp4 HTTP/1.1
User-Agent: ExoPlayerTime/1.0 (Linux;Android 12) ExoPlayerLib/2.7.1
Range: bytes=1207598076-
Accept-Encoding:identity
Host: 127.0.0.1:2222
Connection: Keep-Alive
```
上述情况下如果我们收到包含Range信息的请求时返回的时候就需要额外指定一些信息。HTTP的返回有如下的规则
```Java
// 如果用户拖动了进度条那么HttpRequest就会包含Range信息
// 1.此时contentLength = end - st, 需要返回Content-Length:头
"Content-Length: " + contentLength + "\r\n"
// 2.此时请求的是部分的信息所以返回的Responce的类型是206表示部分内容
HttpStatus.PARTIAL_CONTENT = 206
```
```Java
// 获取文件长度bytes
long contentLen = file.length();
// 从文件获得输入流
InputStream contentIn = file.getInputStream();
// 检查输入数据流是否正常
if (contentLen <= 0 || contentIn == null) {
httpReq.returnBadRequest();
return;
}
// 创建Http返回请求
HTTPResponse httpRes = new HTTPResponse();
// 指定视频数据格式
httpRes.setContentType("video/mpeg4");
if(startFrom == 0 && endAt == 0){
// 请求没有范围信息则返回全部内容状态OK(200)表示全部内容
httpRes.setStatusCode(HTTPStatus.OK);
}else if(startFrom > 0){
// 如果是包含RangeCotent,则需要返回PARTIAL_CONTENT(206)
httpRes.setStatusCode(HTTPStatus.PARTIAL_CONTENT);
httpRes.setContentRange(startFrom,endAt, contentLen);
}
// 设置内容总长度
httpRes.setContentLength(contentLen);
// 指定内容数据流
httpRes.setContentInputStream(contentIn);
// HttpReq提交数据
httpReq.post(httpRes);
contentIn.close();
```
HTTP 视频请求
```Java
// 已知信息
File_length = 2794939639
File_Range_st = bytes=2792308814
// 分析
st = 2792308814
// 由于文件长度是2794939639所以换算的索引是0~2794939639-1
ed = 2794939639 - 1
content_lenght = ( ed - st + 1 )= File_length - 1 - st + 1
= ed - st
```