主要用于大视频的切片上传
主要实现步骤:
- 声明变量
private static int chunks = 0;//视频一共切了多少片
private static int chunk = 0;//当前上传的是第几片
private static int index = 1;//当前上传的是第几片
public static int r = new Random().nextInt();//参数(根据实际情况添加)
- 获取视频信息的工具类
public class FileAccessI implements Serializable {
RandomAccessFile oSavedFile;
long nPos;
public FileAccessI() throws IOException {
this("", 0);
}
public FileAccessI(String sName, long nPos) throws IOException {
oSavedFile = new RandomAccessFile(sName, "rw");
oSavedFile.seek(nPos);
}
public synchronized int write(byte[] b, int nStart, int nLen) {
int n = -1;
try {
oSavedFile.write(b, nStart, nLen);
n = nLen;
} catch (IOException e) {
e.printStackTrace();
}
return n;
}
//获取文件长度
public synchronized Detail getContent(long nStart) {
Detail detail = new Detail();
detail.b = new byte[1024*1024*5];
try {
oSavedFile.seek(nStart);
detail.length = oSavedFile.read(detail.b);
} catch (IOException e) {
e.printStackTrace();
}
return detail;
}
public class Detail {
public byte[] b;
public int length;
}
public long getFileLength() {
Long length = 0l;
try {
length = oSavedFile.length();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return length;
}
}
- 视频切片
/**
* 视频切片上传
* */
public class BlockStreamBody extends AbstractContentBody {
//给MultipartEntity看的2个参数
private long blockSize = 0;//本次分块上传的大小
private String fileName = null;//上传文件名
//writeTo需要的3个参数
private int chunks = 0, chunk = 0;//blockNumber分块数;blockIndex当前第几块
private File targetFile = null;//要上传的文件
private BlockStreamBody(String mimeType) {
super(mimeType);
// TODO Auto-generated constructor stub
}
/**
* 自定义的ContentBody构造子
* @param chunks 分块数
* @param chunk 当前第几块
* @param targetFile 要上传的文件
*/
public BlockStreamBody(int chunks, int chunk, File targetFile) {
this("application/octet-stream");
this.chunks = chunks;//blockNumber初始化
this.chunk = chunk;//blockIndex初始化
this.targetFile = targetFile;//targetFile初始化
this.fileName = targetFile.getName();//fileName初始化
//blockSize初始化
if (chunk < chunks) {//不是最后一块,那就是固定大小了
this.blockSize = UploadGlobalConstant.CLOUD_API_LOGON_SIZE;
} else {//最后一块
this.blockSize = targetFile.length() - UploadGlobalConstant.CLOUD_API_LOGON_SIZE * (chunks - 1);
}
}
@Override
public void writeTo(OutputStream out) throws IOException {
byte b[] = new byte[1024];//暂存容器
RandomAccessFile raf = new RandomAccessFile(targetFile, "r");//负责读取数据
if (chunk == 1) {//第一块
int n = 0;
long readLength = 0;//记录已读字节数
while (readLength <= blockSize - 1024) {//大部分字节在这里读取
n = raf.read(b, 0, 1024);
readLength += 1024;
out.write(b, 0, n);
}
if (readLength <= blockSize) {//余下的不足 1024 个字节在这里读取
n = raf.read(b, 0, (int)(blockSize - readLength));
out.write(b, 0, n);
}
} else if (chunk < chunks) {//既不是第一块,也不是最后一块
raf.seek(UploadGlobalConstant.CLOUD_API_LOGON_SIZE * (chunk - 1));//跳过前[块数*固定大小 ]个字节
int n = 0;
long readLength = 0;//记录已读字节数
while (readLength <= blockSize - 1024) {//大部分字节在这里读取
n = raf.read(b, 0, 1024);
readLength += 1024;
out.write(b, 0, n);
}
if (readLength <= blockSize) {//余下的不足 1024 个字节在这里读取
n = raf.read(b, 0, (int)(blockSize - readLength));
out.write(b, 0, n);
}
} else {//最后一块
raf.seek(UploadGlobalConstant.CLOUD_API_LOGON_SIZE * (chunk - 1));//跳过前[块数*固定大小 ]个字节
int n = 0;
while ((n = raf.read(b, 0, 1024)) != -1) {
out.write(b, 0, n);
}
}
//TODO 最后不要忘掉关闭out/raf
}
@Override
public String getCharset() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getTransferEncoding() {
// TODO Auto-generated method stub
return "binary";
}
@Override
public String getFilename() {
// TODO Auto-generated method stub
return fileName;
}
@Override
public long getContentLength() {
// TODO Auto-generated method stub
return blockSize;
}
}
public void cutFileUpload(final String url, final String video, final String type) {
try {
final File uploadFile = new File(video);
if (!uploadFile.exists()) { //视频文件不存在
if (null != upLoadFinishListener)
upLoadFinishListener.upLoadVideoError("视频文件不存在");
return;
}
FileAccessI fileAccessI = new FileAccessI(video, 0);
Long nStartPos = 0l;
Long length = fileAccessI.getFileLength();
int mBufferSize = 1024 * 1024 * 5; // 每次处理1024 * 100字节
long dd = length / mBufferSize;
chunks = Integer.valueOf(dd + "") + 1;
FileAccessI.Detail detail;
long nRead = 0l;
vedioFileName = generatePicName(video); // 分配一个文件名
long nStart = nStartPos;
ExecutorService executorService = Executors.newFixedThreadPool(chunks);
for (int i = 0; i < chunks; i++) {
Runnable task = new Runnable() {
@Override
public void run() {
postVideo(url, video, type);
}
};
executorService.submit(task);
}
executorService.shutdown();
while (true) {//视频所有子线程都已执行完-进行下一步操作
if (executorService.isTerminated()) {
break;
}
Thread.sleep(1000);
}
} catch (Exception e) {
}
}
分配文件名:目前只做了mp4格式和3gp格式的上传
public String generatePicName(String videoPath) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS", Locale.CHINA);
String filename = "";
if (videoPath.contains("3gp"))
filename = sdf.format(new Date(System.currentTimeMillis())) + ".3gp";
else filename = sdf.format(new Date(System.currentTimeMillis())) + ".mp4";
return filename;
}
- 上传视频
public synchronized void postVideo(final String url, final String videoPath, String type) {
HttpClient httpclient = null;
try {
// 链接超时,请求超时设置
BasicHttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 10 * 1000);
HttpConnectionParams.setSoTimeout(httpParams, 10 * 1000);
// 请求参数设置
httpclient = new DefaultHttpClient(httpParams);
HttpPost post = new HttpPost(
url + "?type=" + type);
MultipartEntity entity = new MultipartEntity();
entity.addPart("rand",
new StringBody(r + "", Charset.forName("UTF-8")));
entity.addPart("chunks", new StringBody(chunks + "", Charset.forName("UTF-8")));//总片数
entity.addPart("chunk", new StringBody((chunk++) + "", Charset.forName("UTF-8")));//当前是第几片
// 上传视频文件
BlockStreamBody body = new BlockStreamBody(chunks, index++, new File(videoPath));
entity.addPart("Filedata", body);
post.setEntity(entity);
HttpResponse resp = httpclient.execute(post);
int statusCode = resp.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
HttpEntity resEntity = resp.getEntity();
String responces = EntityUtils.toString(resEntity);
//上传的返回结果
if (null != responces && !"".equals(responces)) {
}
EntityUtils.getContentCharSet(resEntity);
} else {
}
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
} finally {
try {
httpclient.getConnectionManager().shutdown();
} catch (Exception ignore) {
}
}
}
- 调用
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
Runnable task = new Runnable() {
@Override
public void run() {
chunk = 0;
index = 1;
cutFileUpload(BaseUrl.videoUpUrl, videoPath, type);
}
};
singleThreadExecutor.submit(task);