Skip to content

Instantly share code, notes, and snippets.

@happy-tao
Created May 15, 2019 08:01
Show Gist options
  • Save happy-tao/db1ca97caa8c39e787bd01650d4ba14d to your computer and use it in GitHub Desktop.
Save happy-tao/db1ca97caa8c39e787bd01650d4ba14d to your computer and use it in GitHub Desktop.
AndServer支持206
package com.hoowu.smart.screen.server;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.hoowu.smart.screen.SmartScreenApplication;
import com.hoowu.smart.screen.common.Constants;
import com.hoowu.smart.screen.core.manager.AppManager;
import com.yanzhenjie.andserver.annotation.Interceptor;
import com.yanzhenjie.andserver.framework.HandlerInterceptor;
import com.yanzhenjie.andserver.framework.handler.RequestHandler;
import com.yanzhenjie.andserver.http.HttpRequest;
import com.yanzhenjie.andserver.http.HttpResponse;
import com.yanzhenjie.andserver.util.MediaType;
import com.yanzhenjie.andserver.util.StatusCode;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
@Interceptor
public class PartialContentInterceptor implements HandlerInterceptor {
@Override
public boolean onIntercept(@NonNull HttpRequest request, @NonNull HttpResponse response, @NonNull RequestHandler handler) throws IOException {
String range = request.getHeader("Range");
if (!TextUtils.isEmpty(range)) {
File file = new File(Constants.HOOWU_STORAGE_PATH
+ ((SmartScreenApplication) AppManager.getAppManager().getContext()).agentConfig.getStoreBasePath()
+ request.getURI());
//开始下载位置
long startByte = 0;
//结束下载位置
long endByte = file.length() - 1;
//有range的话
if (range != null && range.contains("bytes=") && range.contains("-")) {
range = range.substring(range.lastIndexOf("=") + 1).trim();
String ranges[] = range.split("-");
try {
//判断range的类型
if (ranges.length == 1) {
//类型一:bytes=-2343
if (range.startsWith("-")) {
endByte = Long.parseLong(ranges[0]);
}
//类型二:bytes=2343-
else if (range.endsWith("-")) {
startByte = Long.parseLong(ranges[0]);
}
}
//类型三:bytes=22-2343
else if (ranges.length == 2) {
startByte = Long.parseLong(ranges[0]);
endByte = Long.parseLong(ranges[1]);
}
} catch (NumberFormatException e) {
startByte = 0;
endByte = file.length() - 1;
}
}
//要下载的长度(为啥要加一问小学数学老师去)
long contentLength = endByte - startByte + 1;
//文件名
String fileName = file.getName();
//文件类型
MediaType contentType = MediaType.getFileMediaType(file.getName());
//各种响应头设置
//参考资料:https://www.ibm.com/developerworks/cn/java/joy-down/index.html
//坑爹地方一:看代码
response.setHeader("Accept-Ranges", "bytes");
//坑爹地方二:http状态码要为206
response.setStatus(StatusCode.SC_PARTIAL_CONTENT);
// response.setHeader("Content-Length", String.valueOf(contentLength));
//坑爹地方三:Content-Range,格式为
// [要下载的开始位置]-[结束位置]/[文件总大小]
response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + file.length());
RandomAccessFile raf = new RandomAccessFile(file, "r");
response.setBody(new RandomFileBody(startByte, endByte, raf, contentLength, contentType));
return true;
} else {
return false;
}
}
}
package com.hoowu.smart.screen.server;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.yanzhenjie.andserver.http.ResponseBody;
import com.yanzhenjie.andserver.util.MediaType;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
public class RandomFileBody implements ResponseBody {
private Long start;
private Long end;
private RandomAccessFile file;
private long mLength;
private MediaType mMediaType;
public RandomFileBody(Long start, Long end, RandomAccessFile file, Long length, MediaType mediaType) {
this.start = start;
this.end = end;
this.file = file;
this.mLength = length;
this.mMediaType = mediaType;
}
@Override
public long contentLength() {
return mLength;
}
@Nullable
@Override
public MediaType contentType() {
return mMediaType;
}
@Override
public void writeTo(@NonNull OutputStream output) {
long transmitted = 0;
try {
byte[] buff = new byte[10240];
int len = 0;
file.seek(start);
//坑爹地方四:判断是否到了最后不足4096(buff的length)个byte这个逻辑((transmitted + len) <= contentLength)要放前面!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//不然会会先读取randomAccessFile,造成后面读取位置出错,找了一天才发现问题所在
while ((transmitted + len) <= mLength && (len = file.read(buff)) != -1) {
output.write(buff, 0, len);
output.flush();
transmitted += len;
}
//处理不足buff.length部分
if (transmitted < mLength) {
len = file.read(buff, 0, (int) (mLength - transmitted));
output.write(buff, 0, len);
output.flush();
transmitted += len;
}
file.close();
} catch (IOException e) {
System.out.println("用户停止下载:" + start + "-" + end + ":" + transmitted);
} finally {
try {
if (file != null) {
file.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment