Created
May 15, 2019 08:01
-
-
Save happy-tao/db1ca97caa8c39e787bd01650d4ba14d to your computer and use it in GitHub Desktop.
AndServer支持206
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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