import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PersistenceContext;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
* 该类表示存储于云端的一个文件
*/
@Entity
@PersistenceContext(unitName="push2mePU")
@Table(name="cloud_file")
public class CloudFile {
public static final long NEVER_EXPIRED = 8888888888888L;
public static final long DEFAULT_EXPIRE = 7*24*60*60*1000;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
@Transient private byte[] data;
private String mimetype;
private String url;
private String hades_path;
private Long expired = System.currentTimeMillis() + DEFAULT_EXPIRE;
private String description;
private String as_pushlink = Boolean.FALSE.toString();
private int size = -1;
private Date upload_time = new Date();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMimetype() {
return mimetype;
}
public void setMimetype(String mimetype) {
this.mimetype = mimetype;
}
public String getHades_path() {
return hades_path;
}
public void setHades_path(String hades_path) {
this.hades_path = hades_path;
}
public Long getExpired() {
return expired;
}
public void setExpired(Long expired) {
this.expired = expired;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public boolean isAs_pushlink() {
return Boolean.valueOf(as_pushlink);
}
public void setAs_pushlink(boolean as_pushlink) {
this.as_pushlink = Boolean.toString(as_pushlink);
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
if(data!=null){
this.size = data.length;
}
}
public Date getUpload_time() {
return upload_time;
}
public void setUpload_time(Date upload_time) {
this.upload_time = upload_time;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("CloudFile [id=");
builder.append(id);
builder.append(", name=");
builder.append(name);
builder.append(", mimetype=");
builder.append(mimetype);
builder.append(", url=");
builder.append(url);
builder.append(", hades_path=");
builder.append(hades_path);
builder.append(", expired=");
builder.append(expired);
builder.append(", description=");
builder.append(description);
builder.append(", as_pushlink=");
builder.append(as_pushlink);
builder.append(", size=");
builder.append(size);
builder.append("]");
return builder.toString();
}
}
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.lenovo.lps.hds.client.ClientFactory;
import com.lenovo.lps.hds.client.ClientInterface;
import com.lenovo.lps.hds.client.LFSOutputStream;
import com.lenovo.lps.hds.shared.exception.HadesException;
import com.lenovo.lps.psb.simdevice.Push2MeUtils;
import com.lenovo.lps.psb.simdevice.domain.CloudFile;
@Service
@Transactional
public class CloudFileService {
private static final Logger logger = LoggerFactory.getLogger(CloudFileService.class);
private static final String BASE_UPLOAD_PATH = "/etc/";
private static final String LFS_USER = "push";
private static final String LFS_URL = "http://lcsp.lenovomm.com/";
@PersistenceContext
private EntityManager em;
private static final AtomicLong uniMark = new AtomicLong(1);
public void save(CloudFile cloudFile,String clientid) throws HadesException{
if(cloudFile==null)
return;
if(cloudFile.getData()!=null && cloudFile.getData().length>0){
cloudFile.setSize(cloudFile.getData().length);
ClientInterface client = ClientFactory.getInstance();
String dir = createPath(clientid);
//尝试建立目录:
try {
client.mkdir(dir, LFS_USER);
} catch (Exception e) {
e.printStackTrace();
}
LFSOutputStream out=null;
String fullpath = dir + Long.toHexString(System.currentTimeMillis()) + "_" + uniMark.incrementAndGet();
out = client.put(fullpath,LFS_USER, true);
try {
out.write(cloudFile.getData());
out.flush();
cloudFile.setHades_path(out.getFileRealPath());
String url =
""
+ client.buildPath(out.getFileRealPath(), "01", cloudFile.getExpired(), 20, 10);
logger.info("Save file success:" + url);
Countor.getInstance().上传内容的总大小.addAndGet(cloudFile.getData().length);
logger.info("Save data to Hades success:" + url);
cloudFile.setUrl(LFS_URL + url);
em.persist(cloudFile);
} catch (Exception e) {
e.printStackTrace();
throw new HadesException(-1);
} finally{
IOUtils.closeQuietly(out);
}
}
}
/**
* 将数据存放在云存储,并在DB中建立索引
* @param data
* @param filename
* @param mimetype
* @param clientid
* @param expired
* @param askink
* @return
* @throws HadesException
*/
public CloudFile seve(byte[] data,String filename,String mimetype,String description,String clientid,long expired,boolean askink) throws HadesException {
logger.info("Save data to Hades: size=" + data.length + ", deviceid=" + clientid);
CloudFile cloudfile = new CloudFile();
cloudfile.setData(data);
cloudfile.setName(filename);
cloudfile.setMimetype(mimetype);
cloudfile.setExpired(expired);
cloudfile.setDescription(description);
cloudfile.setAs_pushlink(askink);
save(cloudfile,clientid);
return cloudfile;
}
public CloudFile getCloudFile(long fileid){
try {
return em.createQuery("select cf from CloudFile cf where id = ?1 and as_pushlink = ?2",CloudFile.class)
.setParameter(1, fileid).setParameter(2, Boolean.TRUE.toString()).getSingleResult();
} catch (Exception e) {
return null;
}
}
@Scheduled(cron="0 0 3 * * ?") /* 每天凌晨3点清除过期文件 */
public void deleteExpiredFiles(){
logger.info("+[Cron Task]++++++++++ Start deleteExpiredFiles ++++++++++++");
if(Push2MeUtils.isMasterNode()){
List<CloudFile> filesToDel =
em.createQuery("select c from CloudFile c where c.expired < ?1", CloudFile.class)
.setParameter(1, System.currentTimeMillis())
.getResultList();
ClientInterface client = ClientFactory.getInstance();
for(CloudFile cf:filesToDel){
logger.info("Deleting cloud file: " + cf);
try {
client.delete(cf.getHades_path());
} catch (HadesException e) {
e.printStackTrace();
}
try {
em.remove(cf);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private static String createPath(String clientid){
StringBuilder sb = new StringBuilder();
sb.append(BASE_UPLOAD_PATH);
if(clientid!=null){
sb.append(clientid.hashCode()%1000) //为了减少单个目录内的文件数,增加一层目录
.append('/')
.append(clientid) //为了减少单个目录内的文件数,再增加一层目录
.append('/');
}else{
sb.append("shared_files/")
.append(System.currentTimeMillis()%1000)
.append('/');
}
return sb.toString();
}
}