Upload big file using java.
Basically, read a big file into small parts and upload. When all file parts upload is complete, combine at server.
- Read the big file into several small parts. Considering I/O contention, use just one thread; Considering memory usage, read file part by part into fixed size queue.
- Upload every readed file part. Usually multiple threads would be better, but can't too much, default threads count is 5.
- After all parts uploaded, notify server to combine.
- Can retry the specific parts only if failed to process.
- Save recieved file parts.
- Combine all parts by notification.
- Producer/Consumer pattern.
- Communicate read and upload processes by BlockingQueue.
- Uploading is using Apache HttpComponents currently. There can be other implementations.
- Can be used in the android. Please refer to BigFileUploadAndroid。
Please refer to cn.clxy.upload.Config.
Please note that the maximum memory usage might be:
PART_SIZE * (MAX_UPLOAD + MAX_READ - 1)
UploadFileService service = new UploadFileService(yourFileName);
service.upload();
UploadFileService service = new UploadFileService(yourFileName);
service.retry(1, 2);
Because it is via HTTP, so it can be in any language, such as Java, PHP, Python, etc. Here is a java example.
...
try (FileOutputStream dest = new FileOutputStream(destFile, true)) {
FileChannel dc = dest.getChannel();// the final big file.
for (long i = 0; i < count; i++) {
File partFile = new File(destFileName + "." + i);// every small parts.
if (!partFile.exists()) {
break;
}
try (FileInputStream part = new FileInputStream(partFile)) {
FileChannel pc = part.getChannel();
pc.transferTo(0, pc.size(), dc);// combine.
}
partFile.delete();
}
statusCode = OK;// set ok at last.
} catch (Exception e) {
log.error("combine failed.", e);
}
使用Java上传大文件的实现。
基本上是将大文件拆成小块,读取,上传。当所有文件块上传完成后,合并。
- 读取文件到小的文件块。考虑到I/O竞争只用单线程;考虑到内存消耗采取分批读取。
- 将读取的文件块上传。通常多个线程会好些,但是太多又不行,默认用5线程上传。
- 所有文件块全部上传后,通知服务器合并。
- 如果有部分文件块处理失败,可以重试失败部分。
- 收到文件块后直接保存。
- 收到通知后合并所有文件块。
- 使用生产/消费者模式。
- 读取和上传的通信使用BlockingQueue。
- 目前上传用Apache HttpComponents。可以有其他实现。
- 可以用在Android上。请参考BigFileUploadAndroid。
请注意内存的最大使用量可能是:
PART_SIZE * (MAX_UPLOAD + MAX_READ - 1)
UploadFileService service = new UploadFileService(yourFileName);
service.upload();
UploadFileService service = new UploadFileService(yourFileName);
service.retry(1, 2);
由于是经由HTTP上传,所以可以是任何语言如Java,PHP,Python等。 下面是合并文件的Java实例。
...
try (FileOutputStream dest = new FileOutputStream(destFile, true)) {
FileChannel dc = dest.getChannel();// 最终的大文件。
for (long i = 0; i < count; i++) {
File partFile = new File(destFileName + "." + i);// 每个文件块。
if (!partFile.exists()) {
break;
}
try (FileInputStream part = new FileInputStream(partFile)) {
FileChannel pc = part.getChannel();
pc.transferTo(0, pc.size(), dc);// 合并。
}
partFile.delete();
}
statusCode = OK;// 最终设状态OK。
} catch (Exception e) {
log.error("combine failed.", e);
}