package chat.upload;
|
|
import java.io.File;
|
import java.io.RandomAccessFile;
|
import java.text.SimpleDateFormat;
|
import java.util.Date;
|
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import chat.security.DES;
|
|
import chat.server.im.ResultPool;
|
import io.netty.buffer.ByteBuf;
|
import io.netty.handler.codec.http.FullHttpRequest;
|
import io.netty.handler.codec.http.HttpContent;
|
import io.netty.handler.codec.http.HttpHeaders;
|
import io.netty.handler.codec.http.multipart.Attribute;
|
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
|
import io.netty.handler.codec.http.multipart.FileUpload;
|
import io.netty.handler.codec.http.multipart.HttpDataFactory;
|
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
|
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
|
import io.netty.util.internal.StringUtil;
|
|
public class UploadFile {
|
|
private static final String KEY = "imfile";
|
private static final Logger logger = LoggerFactory.getLogger(UploadFile.class);
|
private static final HttpDataFactory factory = new DefaultHttpDataFactory(false);
|
|
public static String multipartUpload(FullHttpRequest request, String requestId) {
|
HttpPostRequestDecoder decoder = null;
|
String key = "";
|
try {
|
decoder = new HttpPostRequestDecoder(factory, request);
|
} catch (Exception e) {
|
logger.error("Failed to decode file data!", e);
|
e.printStackTrace();
|
return "";
|
}
|
|
if (decoder != null) {
|
if (request instanceof HttpContent) {
|
HttpContent chunk = (HttpContent) request;
|
try {
|
decoder.offer(chunk);
|
} catch (Exception e) {
|
e.printStackTrace();
|
return "";
|
}
|
|
long fileTotalSize = 0;
|
if (request.headers().contains("X-File-Total-Size")) {
|
try {
|
fileTotalSize = Integer.parseInt(request.headers().get("X-File-Total-Size"));
|
} catch (Exception e) {
|
logger.warn("invalid X-File-Total-Size value!");
|
}
|
}
|
|
UploadFile uploadFile = new UploadFile();
|
key = uploadFile.readHttpDataChunkByChunk(decoder, requestId, HttpHeaders.isKeepAlive(request));
|
}
|
}
|
return key;
|
}
|
|
private String readHttpDataChunkByChunk(HttpPostRequestDecoder decoder, String requestId, boolean isKeepAlive) {
|
String returnValue = "";
|
try {
|
int[] bucket = new int[1];
|
bucket[0] = -1;
|
while (decoder.hasNext()) {
|
InterfaceHttpData data = decoder.next();
|
if (data != null) {
|
try {
|
returnValue = writeFileUploadData(data, requestId, isKeepAlive, bucket);
|
if (returnValue == null) {
|
break;
|
}
|
} finally {
|
data.release();
|
}
|
}
|
}
|
} catch(Exception e) {
|
logger.info("chunk end");
|
return returnValue;
|
//e.printStackTrace();
|
}
|
return returnValue;
|
}
|
|
private String writeFileUploadData(InterfaceHttpData data, String requestId, boolean isKeepAlive, int[] bucket) {
|
String relativePath = "";
|
try {
|
if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
|
FileUpload fileUpload = (FileUpload) data;
|
|
String remoteFileName = fileUpload.getFilename();
|
long remoteFileSize = fileUpload.length();
|
|
if(bucket[0] == -1) {
|
logger.info("Not authenticated!");
|
return null;
|
}
|
|
if (StringUtil.isNullOrEmpty(remoteFileName)) {
|
logger.info("remoteFileName is empty!");
|
return null;
|
}
|
|
if (StringUtil.isNullOrEmpty(requestId)) {
|
logger.info("requestId is empty!");
|
return null;
|
}
|
|
if (remoteFileSize > 100 * 1024 * 1024) {
|
logger.info("file over limit!(" + remoteFileSize + ")");
|
return null;
|
}
|
|
String remoteFileExt = "";
|
if (remoteFileName.lastIndexOf(".") == -1) {
|
remoteFileExt = "octetstream";
|
remoteFileName = remoteFileName + "." + remoteFileExt;
|
|
} else {
|
remoteFileExt = getFileExt(remoteFileName);
|
}
|
|
if (StringUtil.isNullOrEmpty(remoteFileExt) || remoteFileExt.equals("ing")) {
|
logger.info("Invalid file extention name");
|
return null;
|
}
|
|
int remoteFileTotalSize = (int) remoteFileSize;
|
|
ByteBuf byteBuf = null;
|
int savedThunkSize = 0;
|
int offset = 0;
|
|
Date nowTime = new Date();
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/HH");
|
String datePath = sdf.format(nowTime);
|
|
datePath = "fs/" + bucket[0] + "/" + datePath;
|
String dir = "D:/media/" + datePath;
|
|
File dirFile = new File(dir);
|
if (!dirFile.exists()) {
|
if (!dirFile.mkdirs()) {
|
logger.info("无法创建文件");
|
return null;
|
}
|
}
|
|
String filePath = dir + "/" + (StringUtil.isNullOrEmpty(remoteFileName) ? requestId : remoteFileName);
|
|
File tmpFile = new File(filePath);
|
|
boolean isError = false;
|
|
while (true) {
|
byte[] thunkData;
|
try {
|
byteBuf = fileUpload.getChunk(128 * 1024);
|
int readableBytesSize = byteBuf.readableBytes();
|
thunkData = new byte[readableBytesSize];
|
byteBuf.readBytes(thunkData);
|
|
put(tmpFile, offset, thunkData);
|
|
savedThunkSize += readableBytesSize;
|
offset += readableBytesSize;
|
|
if (savedThunkSize >= remoteFileSize) {
|
byteBuf.release();
|
fileUpload.release();
|
|
relativePath = datePath + "/" + (StringUtil.isNullOrEmpty(remoteFileName) ? requestId : remoteFileName);
|
|
break;
|
}
|
} catch(Exception e) {
|
logger.info("save thunckData error!");
|
if (fileUpload != null) {
|
fileUpload.release();
|
}
|
|
if (byteBuf != null) {
|
byteBuf.release();
|
}
|
isError = true;
|
|
return null;
|
} finally {
|
thunkData = null;
|
if (isError) {
|
tmpFile.delete();
|
}
|
}
|
}
|
}
|
else if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
|
Attribute attribute = (Attribute) data;
|
if (attribute.getName().equals("token")) {
|
String token = attribute.getValue();
|
|
try {
|
bucket[0] = validateToken(token);
|
relativePath = "";
|
} catch(Exception e) {
|
logger.info("无效的token!");
|
return null;
|
}
|
}
|
}
|
} catch(Exception e) {
|
logger.info("writeHttpData error!", e);
|
return null;
|
}
|
return relativePath;
|
}
|
|
public String getFileExt(String fileName) {
|
int index = fileName.lastIndexOf(".");
|
if (index == -1) {
|
return "";
|
}
|
|
return fileName.substring(index + 1).toLowerCase();
|
}
|
|
public void put(File file, long pos, byte[] data) throws Exception {
|
RandomAccessFile raf = null;
|
try {
|
raf = new RandomAccessFile(file, "rwd");
|
raf.seek(pos);
|
raf.write(data);
|
} finally {
|
try {
|
if (raf != null) {
|
raf.close();
|
}
|
} catch (Exception e) {
|
logger.info("release error!");
|
e.printStackTrace();
|
}
|
}
|
}
|
|
public int validateToken(String token) throws InvalidateTokenExecption {
|
try {
|
String signKey = DES.decryptDES(token);
|
String[] parts = signKey.split("\\|");
|
if(parts.length == 3) {
|
if(parts[0].equals(KEY)) {
|
long timestamp = Long.parseLong(parts[1]);
|
if(Math.abs(System.currentTimeMillis() - timestamp) < 2 * 60 * 60 * 1000) {
|
return Integer.parseInt(parts[2]);
|
}
|
}
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
throw new InvalidateTokenExecption();
|
}
|
|
public static class InvalidateTokenExecption extends Exception {}
|
|
}
|