[DEV] add other common elements
This commit is contained in:
parent
044889129a
commit
f4ec9e8d82
@ -19,6 +19,7 @@ Read instruction for tocken in ~/.m2/setting.xml
|
||||
|
||||
release:
|
||||
|
||||
export PATH=/usr/lib/jvm/java-18-openjdk/bin:$PATH
|
||||
mvn install
|
||||
mvn deploy
|
||||
|
||||
|
2
pom.xml
2
pom.xml
@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>kangaroo-and-rabbit</groupId>
|
||||
<artifactId>archidata</artifactId>
|
||||
<version>0.1.2</version>
|
||||
<version>0.1.3</version>
|
||||
<properties>
|
||||
<jaxrs.version>2.1</jaxrs.version>
|
||||
<jersey.version>2.32</jersey.version>
|
||||
|
@ -4,7 +4,7 @@ import org.kar.archidata.db.DBConfig;
|
||||
import org.kar.archidata.util.ConfigBaseVariable;
|
||||
|
||||
public class GlobalConfiguration {
|
||||
public static DBConfig dbConfig = null;;
|
||||
public static DBConfig dbConfig = null;
|
||||
|
||||
static {
|
||||
dbConfig = new DBConfig(ConfigBaseVariable.getDBHost(),
|
||||
|
@ -520,9 +520,42 @@ public class SqlWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
static void addElement(PreparedStatement ps, Object value, int iii) throws Exception {
|
||||
if (value.getClass() == Long.class) {
|
||||
ps.setLong(iii, (Long)value);
|
||||
} else if (value.getClass() == Integer.class) {
|
||||
ps.setInt(iii, (Integer)value);
|
||||
} else if (value.getClass() == String.class) {
|
||||
ps.setString(iii, (String)value);
|
||||
} else if (value.getClass() == Short.class) {
|
||||
ps.setShort(iii, (Short)value);
|
||||
} else if (value.getClass() == Byte.class) {
|
||||
ps.setByte(iii, (Byte)value);
|
||||
} else if (value.getClass() == Float.class) {
|
||||
ps.setFloat(iii, (Float)value);
|
||||
} else if (value.getClass() == Double.class) {
|
||||
ps.setDouble(iii, (Double)value);
|
||||
} else if (value.getClass() == Boolean.class) {
|
||||
ps.setBoolean(iii, (Boolean)value);
|
||||
} else if (value.getClass() == Boolean.class) {
|
||||
ps.setBoolean(iii, (Boolean)value);
|
||||
} else if (value.getClass() == Timestamp.class) {
|
||||
ps.setTimestamp(iii, (Timestamp)value);
|
||||
} else if (value.getClass() == Date.class) {
|
||||
ps.setDate(iii, (Date)value);
|
||||
} else {
|
||||
throw new Exception("Not manage type ==> need to add it ...");
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T getWith(Class<T> clazz, String key, String value) throws Exception {
|
||||
//public static NodeSmall createNode(String typeInNode, String name, String description, Long parentId) {
|
||||
|
||||
return getWhere(clazz, key, "=", value);
|
||||
}
|
||||
|
||||
public static <T> T getWhere(Class<T> clazz, String key, String operator, Object value ) throws Exception {
|
||||
return getWhere(clazz, key, operator, value, null, null, null);
|
||||
}
|
||||
public static <T> T getWhere(Class<T> clazz, String key, String operator, Object value, String key2, String operator2, Object value2 ) throws Exception {
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
T out = null;
|
||||
// real add in the BDD:
|
||||
@ -535,13 +568,8 @@ public class SqlWrapper {
|
||||
//query.append(" SET ");
|
||||
|
||||
boolean firstField = true;
|
||||
Field primaryKeyField = null;
|
||||
int count = 0;
|
||||
for (Field elem : clazz.getFields()) {
|
||||
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
|
||||
if (primaryKey) {
|
||||
primaryKeyField = elem;
|
||||
}
|
||||
ModelLink linkGeneric = getLinkMode(elem);
|
||||
if (linkGeneric != ModelLink.NONE) {
|
||||
continue;
|
||||
@ -564,17 +592,28 @@ public class SqlWrapper {
|
||||
query.append(" ");
|
||||
query.append(tableName);
|
||||
query.append(".");
|
||||
|
||||
query.append(name);
|
||||
}
|
||||
query.append("\n FROM `");
|
||||
query.append(" FROM `");
|
||||
query.append(tableName);
|
||||
query.append("` ");
|
||||
query.append("\n WHERE ");
|
||||
query.append(" WHERE ");
|
||||
query.append(tableName);
|
||||
query.append(".");
|
||||
query.append(key);
|
||||
query.append(" = ?");
|
||||
query.append("\n LIMIT 1 ");
|
||||
query.append(" ");
|
||||
query.append(operator);
|
||||
query.append(" ?");
|
||||
if (key2 != null) {
|
||||
query.append(" AND ");
|
||||
query.append(tableName);
|
||||
query.append(".");
|
||||
query.append(key2);
|
||||
query.append(" ");
|
||||
query.append(operator2);
|
||||
query.append(" ?");
|
||||
}
|
||||
/*
|
||||
query.append(" AND ");
|
||||
query.append(tableName);
|
||||
@ -585,7 +624,10 @@ public class SqlWrapper {
|
||||
// prepare the request:
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query.toString(), Statement.RETURN_GENERATED_KEYS);
|
||||
int iii = 1;
|
||||
ps.setString(iii++, value);
|
||||
addElement(ps, value, iii++);
|
||||
if (key2 != null) {
|
||||
addElement(ps, value2, iii++);
|
||||
}
|
||||
// execute the request
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
@ -621,11 +663,9 @@ public class SqlWrapper {
|
||||
entry = null;
|
||||
return out;
|
||||
}
|
||||
|
||||
public static <T> T getWhere(Class<T> clazz, String key, String operator, Object value ) throws Exception {
|
||||
|
||||
public static <T> List<T> getsWhere(Class<T> clazz, String key, String operator, Object value ) throws Exception {
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
T out = null;
|
||||
List<T> outs = new ArrayList<>();
|
||||
// real add in the BDD:
|
||||
try {
|
||||
String tableName = getTableName(clazz);
|
||||
@ -683,31 +723,7 @@ public class SqlWrapper {
|
||||
// prepare the request:
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query.toString(), Statement.RETURN_GENERATED_KEYS);
|
||||
int iii = 1;
|
||||
if (value.getClass() == Long.class) {
|
||||
ps.setLong(iii++, (Long)value);
|
||||
} else if (value.getClass() == Integer.class) {
|
||||
ps.setInt(iii++, (Integer)value);
|
||||
} else if (value.getClass() == String.class) {
|
||||
ps.setString(iii++, (String)value);
|
||||
} else if (value.getClass() == Short.class) {
|
||||
ps.setShort(iii++, (Short)value);
|
||||
} else if (value.getClass() == Byte.class) {
|
||||
ps.setByte(iii++, (Byte)value);
|
||||
} else if (value.getClass() == Float.class) {
|
||||
ps.setFloat(iii++, (Float)value);
|
||||
} else if (value.getClass() == Double.class) {
|
||||
ps.setDouble(iii++, (Double)value);
|
||||
} else if (value.getClass() == Boolean.class) {
|
||||
ps.setBoolean(iii++, (Boolean)value);
|
||||
} else if (value.getClass() == Boolean.class) {
|
||||
ps.setBoolean(iii++, (Boolean)value);
|
||||
} else if (value.getClass() == Timestamp.class) {
|
||||
ps.setTimestamp(iii++, (Timestamp)value);
|
||||
} else if (value.getClass() == Date.class) {
|
||||
ps.setDate(iii++, (Date)value);
|
||||
} else {
|
||||
throw new Exception("Not manage type ==> need to add it ...");
|
||||
}
|
||||
addElement(ps, value, iii++);
|
||||
// execute the request
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
@ -733,7 +749,8 @@ public class SqlWrapper {
|
||||
setValueFromDb(elem.getType(), data, count, elem, rs);
|
||||
count++;
|
||||
}
|
||||
out = (T)data;
|
||||
T out = (T)data;
|
||||
outs.add(out);
|
||||
}
|
||||
|
||||
} catch (SQLException ex) {
|
||||
@ -741,7 +758,7 @@ public class SqlWrapper {
|
||||
}
|
||||
entry.disconnect();
|
||||
entry = null;
|
||||
return out;
|
||||
return outs;
|
||||
}
|
||||
|
||||
public static <T> T get(Class<T> clazz, long id) throws Exception {
|
||||
@ -1021,6 +1038,22 @@ public class SqlWrapper {
|
||||
entry.disconnect();
|
||||
}
|
||||
}
|
||||
public static void unsetDelete(Class<?> clazz, long id) throws Exception {
|
||||
String tableName = getTableName(clazz);
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
String query = "UPDATE `" + tableName + "` SET `modify_date`=now(3), `deleted`=false WHERE `id` = ?";
|
||||
try {
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query);
|
||||
int iii = 1;
|
||||
ps.setLong(iii++, id);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
throw new ExceptionDBInterface(500, "SQL error: " + ex.getMessage());
|
||||
} finally {
|
||||
entry.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public static String createTable(Class<?> clazz) throws Exception {
|
||||
String tableName = getTableName(clazz);
|
||||
|
@ -6,12 +6,6 @@ import org.kar.archidata.util.JWTWrapper;
|
||||
public class UpdateJwtPublicKey extends Thread {
|
||||
boolean kill = false;
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(1000*20, 0);
|
||||
} catch (InterruptedException e2) {
|
||||
// TODO Auto-generated catch block
|
||||
e2.printStackTrace();
|
||||
}
|
||||
while (this.kill == false) {
|
||||
// need to uppgrade when server call us...
|
||||
try {
|
||||
|
@ -13,76 +13,17 @@ public class UserDB {
|
||||
|
||||
public static User getUsers(long userId) throws Exception {
|
||||
return SqlWrapper.get(User.class, userId);
|
||||
/*
|
||||
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
|
||||
String query = "SELECT * FROM user WHERE id = ?";
|
||||
try {
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query);
|
||||
ps.setLong(1, userId);
|
||||
ResultSet rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
User out = new User(rs);
|
||||
entry.disconnect();
|
||||
return out;
|
||||
}
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
entry.disconnect();
|
||||
return null;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public static User getUserOrCreate(long userId, String userLogin) throws Exception {
|
||||
User user = getUsers(userId);
|
||||
if (user != null) {
|
||||
/*
|
||||
boolean blocked = false;
|
||||
boolean removed = false;
|
||||
if (user.email != userOAuth.email || user.login != userOAuth.login || user.blocked != blocked || user.removed != removed) {
|
||||
updateUsersInfoFromOAuth(userOAuth.id, userOAuth.email, userOAuth.login, blocked, removed);
|
||||
} else {
|
||||
updateUsersConnectionTime(userOAuth.id);
|
||||
}
|
||||
return getUsers(userOAuth.id);
|
||||
*/
|
||||
return user;
|
||||
}
|
||||
createUsersInfoFromOAuth(userId, userLogin);
|
||||
return getUsers(userId);
|
||||
}
|
||||
/*
|
||||
private static void updateUsersConnectionTime(long userId) {
|
||||
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
|
||||
String query = "UPDATE `user` SET `lastConnection`=now(3) WHERE `id` = ?";
|
||||
try {
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query);
|
||||
ps.setLong(1, userId);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
entry.disconnect();
|
||||
}
|
||||
|
||||
private static void updateUsersInfoFromOAuth(long userId, String email, String login, boolean blocked, boolean removed) {
|
||||
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
|
||||
String query = "UPDATE `user` SET `login`=?, `email`=?, `lastConnection`=now(3), `blocked`=?, `removed`=? WHERE id = ?";
|
||||
try {
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query);
|
||||
ps.setString(1, login);
|
||||
ps.setString(2, email);
|
||||
ps.setString(3, blocked ? "TRUE" : "FALSE");
|
||||
ps.setString(4, removed ? "TRUE" : "FALSE");
|
||||
ps.setLong(5, userId);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
entry.disconnect();
|
||||
}
|
||||
*/
|
||||
|
||||
private static void createUsersInfoFromOAuth(long userId, String login) {
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
|
12
src/org/kar/archidata/annotation/SQLForeignKey.java
Normal file
12
src/org/kar/archidata/annotation/SQLForeignKey.java
Normal file
@ -0,0 +1,12 @@
|
||||
package org.kar.archidata.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SQLForeignKey {
|
||||
String value();
|
||||
}
|
@ -5,7 +5,6 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@NameBinding
|
||||
|
429
src/org/kar/archidata/api/DataResource.java
Normal file
429
src/org/kar/archidata/api/DataResource.java
Normal file
@ -0,0 +1,429 @@
|
||||
package org.kar.archidata.api;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
import org.kar.archidata.filter.GenericContext;
|
||||
import org.kar.archidata.model.Data;
|
||||
import org.kar.archidata.SqlWrapper;
|
||||
import org.kar.archidata.annotation.security.PermitTokenInURI;
|
||||
import org.kar.archidata.annotation.security.RolesAllowed;
|
||||
import org.kar.archidata.util.ConfigBaseVariable;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.CacheControl;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.SecurityContext;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
// https://stackoverflow.com/questions/35367113/jersey-webservice-scalable-approach-to-download-file-and-reply-to-client
|
||||
// https://gist.github.com/aitoroses/4f7a2b197b732a6a691d
|
||||
|
||||
@Path("/data")
|
||||
@Produces({MediaType.APPLICATION_JSON})
|
||||
public class DataResource {
|
||||
private final static int CHUNK_SIZE = 1024 * 1024; // 1MB chunks
|
||||
private final static int CHUNK_SIZE_IN = 50 * 1024 * 1024; // 1MB chunks
|
||||
/**
|
||||
* Upload some datas
|
||||
*/
|
||||
private static long tmpFolderId = 1;
|
||||
|
||||
private static void createFolder(String path) throws IOException {
|
||||
if (!Files.exists(java.nio.file.Path.of(path))) {
|
||||
//Log.print("Create folder: " + path);
|
||||
Files.createDirectories(java.nio.file.Path.of(path));
|
||||
}
|
||||
}
|
||||
|
||||
public static long getTmpDataId() {
|
||||
return tmpFolderId++;
|
||||
}
|
||||
|
||||
public static String getTmpFileInData(long tmpFolderId) {
|
||||
String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId;
|
||||
try {
|
||||
createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public static String getFileData(long tmpFolderId) {
|
||||
String filePath = ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator + "data";
|
||||
try {
|
||||
createFolder(ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public static Data getWithSha512(String sha512) {
|
||||
System.out.println("find sha512 = " + sha512);
|
||||
try {
|
||||
return SqlWrapper.getWhere(Data.class, "sha512", "=", sha512);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Data getWithId(long id) {
|
||||
System.out.println("find id = " + id);
|
||||
try {
|
||||
return SqlWrapper.get(Data.class, id);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Data createNewData(long tmpUID, String originalFileName, String sha512) throws IOException {
|
||||
// determine mime type:
|
||||
Data injectedData = new Data();
|
||||
String mimeType = "";
|
||||
String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1);
|
||||
switch (extension.toLowerCase()) {
|
||||
case "jpg":
|
||||
case "jpeg":
|
||||
mimeType = "image/jpeg";
|
||||
break;
|
||||
case "png":
|
||||
mimeType = "image/png";
|
||||
break;
|
||||
case "webp":
|
||||
mimeType = "image/webp";
|
||||
break;
|
||||
case "mka":
|
||||
mimeType = "audio/x-matroska";
|
||||
break;
|
||||
case "mkv":
|
||||
mimeType = "video/x-matroska";
|
||||
break;
|
||||
case "webm":
|
||||
mimeType = "video/webm";
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Can not find the mime type of data input: '" + extension + "'");
|
||||
}
|
||||
injectedData.mimeType = mimeType;
|
||||
injectedData.sha512 = sha512;
|
||||
String tmpPath = getTmpFileInData(tmpUID);
|
||||
injectedData.size = Files.size(Paths.get(tmpPath));
|
||||
|
||||
try {
|
||||
injectedData = SqlWrapper.insert(injectedData);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
String mediaPath = getFileData(injectedData.id);
|
||||
System.out.println("src = " + tmpPath);
|
||||
System.out.println("dst = " + mediaPath);
|
||||
Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE);
|
||||
System.out.println("Move done");
|
||||
return injectedData;
|
||||
}
|
||||
|
||||
public static String saveTemporaryFile(InputStream uploadedInputStream, long idData) {
|
||||
return saveFile(uploadedInputStream, DataResource.getTmpFileInData(idData));
|
||||
}
|
||||
|
||||
public static void removeTemporaryFile(long idData) {
|
||||
String filepath = DataResource.getTmpFileInData(idData);
|
||||
if (Files.exists(Paths.get(filepath))) {
|
||||
try {
|
||||
Files.delete(Paths.get(filepath));
|
||||
} catch (IOException e) {
|
||||
System.out.println("can not delete temporary file : " + Paths.get(filepath));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save uploaded file to a defined location on the server
|
||||
static String saveFile(InputStream uploadedInputStream, String serverLocation) {
|
||||
String out = "";
|
||||
try {
|
||||
OutputStream outpuStream = new FileOutputStream(new File(
|
||||
serverLocation));
|
||||
int read = 0;
|
||||
byte[] bytes = new byte[CHUNK_SIZE_IN];
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
|
||||
outpuStream = new FileOutputStream(new File(serverLocation));
|
||||
while ((read = uploadedInputStream.read(bytes)) != -1) {
|
||||
//System.out.println("write " + read);
|
||||
md.update(bytes, 0, read);
|
||||
outpuStream.write(bytes, 0, read);
|
||||
}
|
||||
System.out.println("Flush input stream ... " + serverLocation);
|
||||
System.out.flush();
|
||||
outpuStream.flush();
|
||||
outpuStream.close();
|
||||
// create the end of sha512
|
||||
byte[] sha512Digest = md.digest();
|
||||
// convert in hexadecimal
|
||||
out = bytesToHex(sha512Digest);
|
||||
uploadedInputStream.close();
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Can not write in temporary file ... ");
|
||||
ex.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
System.out.println("Can not find sha512 algorithms");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public Data getSmall(Long id) {
|
||||
try {
|
||||
return SqlWrapper.get(Data.class, id);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/upload/")
|
||||
@Consumes({MediaType.MULTIPART_FORM_DATA})
|
||||
@RolesAllowed("ADMIN")
|
||||
public Response uploadFile(@Context SecurityContext sc, @FormDataParam("file") InputStream fileInputStream, @FormDataParam("file") FormDataContentDisposition fileMetaData) {
|
||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
System.out.println("===================================================");
|
||||
System.out.println("== DATA uploadFile " + (gc==null?"null":gc.user));
|
||||
System.out.println("===================================================");
|
||||
//public NodeSmall uploadFile(final FormDataMultiPart form) {
|
||||
System.out.println("Upload file: ");
|
||||
String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId++;
|
||||
try {
|
||||
createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
saveFile(fileInputStream, filePath);
|
||||
return Response.ok("Data uploaded successfully !!").build();
|
||||
//return null;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@PermitTokenInURI
|
||||
@RolesAllowed("USER")
|
||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||
public Response retriveDataId(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id) throws Exception {
|
||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
//System.out.println("===================================================");
|
||||
System.out.println("== DATA retriveDataId ? id=" + id + " user=" + (gc==null?"null":gc.user));
|
||||
//System.out.println("===================================================");
|
||||
Data value = getSmall(id);
|
||||
if (value == null) {
|
||||
Response.status(404).
|
||||
entity("media NOT FOUND: " + id).
|
||||
type("text/plain").
|
||||
build();
|
||||
}
|
||||
return buildStream(ConfigBaseVariable.getMediaDataFolder() + File.separator + id + File.separator + "data", range, value.mimeType);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("thumbnail/{id}")
|
||||
@RolesAllowed("USER")
|
||||
@PermitTokenInURI
|
||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||
//@CacheMaxAge(time = 10, unit = TimeUnit.DAYS)
|
||||
public Response retriveDataThumbnailId(@Context SecurityContext sc,
|
||||
@QueryParam(HttpHeaders.AUTHORIZATION) String token,
|
||||
@HeaderParam("Range") String range,
|
||||
@PathParam("id") Long id) throws Exception {
|
||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
//System.out.println("===================================================");
|
||||
//System.out.println("== DATA retriveDataThumbnailId ? " + (gc==null?"null":gc.user));
|
||||
//System.out.println("===================================================");
|
||||
Data value = getSmall(id);
|
||||
if (value == null) {
|
||||
return Response.status(404).
|
||||
entity("media NOT FOUND: " + id).
|
||||
type("text/plain").
|
||||
build();
|
||||
}
|
||||
String filePathName = ConfigBaseVariable.getMediaDataFolder() + File.separator + id + File.separator + "data";
|
||||
if ( value.mimeType.contentEquals("image/jpeg")
|
||||
|| value.mimeType.contentEquals("image/png")
|
||||
// || value.mimeType.contentEquals("image/webp")
|
||||
) {
|
||||
// reads input image
|
||||
//System.out.println("Read path: " + filePathName);
|
||||
File inputFile = new File(filePathName);
|
||||
if (!inputFile.exists()) {
|
||||
return Response.status(500).
|
||||
entity("Internal Error: Media is NOT FOUNDABLE: " + id).
|
||||
type("text/plain").
|
||||
build();
|
||||
}
|
||||
BufferedImage inputImage = ImageIO.read(inputFile);
|
||||
int scaledWidth = 250;
|
||||
int scaledHeight = (int)((float)inputImage.getHeight() / (float)inputImage.getWidth() * (float) scaledWidth);
|
||||
// creates output image
|
||||
BufferedImage outputImage = new BufferedImage(scaledWidth,
|
||||
scaledHeight, inputImage.getType());
|
||||
|
||||
// scales the input image to the output image
|
||||
Graphics2D g2d = outputImage.createGraphics();
|
||||
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
|
||||
g2d.dispose();
|
||||
// create the output stream:
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
// TODO: check how to remove buffer file !!! here, it is not needed at all...
|
||||
ImageIO.write( outputImage, "JPG", baos);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return Response.status(500).
|
||||
entity("Internal Error: resize fail: " + e.getMessage()).
|
||||
type("text/plain").
|
||||
build();
|
||||
}
|
||||
byte[] imageData = baos.toByteArray();
|
||||
//Response.ok(new ByteArrayInputStream(imageData)).build();
|
||||
Response.ResponseBuilder out = Response.ok(imageData)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, imageData.length);
|
||||
out.type("image/jpeg");
|
||||
// TODO: move this in a decorator !!!
|
||||
CacheControl cc = new CacheControl();
|
||||
cc.setMaxAge(3600);
|
||||
cc.setNoCache(false);
|
||||
out.cacheControl(cc);
|
||||
return out.build();
|
||||
}
|
||||
return buildStream(filePathName, range, value.mimeType);
|
||||
}
|
||||
//@Secured
|
||||
@GET
|
||||
@Path("{id}/{name}")
|
||||
@PermitTokenInURI
|
||||
@RolesAllowed("USER")
|
||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||
public Response retriveDataFull(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id, @PathParam("name") String name) throws Exception {
|
||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
//System.out.println("===================================================");
|
||||
System.out.println("== DATA retriveDataFull ? id=" + id + " user=" + (gc==null?"null":gc.user));
|
||||
//System.out.println("===================================================");
|
||||
Data value = getSmall(id);
|
||||
if (value == null) {
|
||||
Response.status(404).
|
||||
entity("media NOT FOUND: " + id).
|
||||
type("text/plain").
|
||||
build();
|
||||
}
|
||||
return buildStream(ConfigBaseVariable.getMediaDataFolder() + File.separator + id + File.separator + "data", range, value.mimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapted from http://stackoverflow.com/questions/12768812/video-streaming-to-ipad-does-not-work-with-tapestry5/12829541#12829541
|
||||
*
|
||||
* @param range range header
|
||||
* @return Streaming output
|
||||
* @throws Exception IOException if an error occurs in streaming.
|
||||
*/
|
||||
private Response buildStream(final String filename, final String range, String mimeType) throws Exception {
|
||||
File file = new File(filename);
|
||||
//System.out.println("request range : " + range);
|
||||
// range not requested : Firefox does not send range headers
|
||||
if (range == null) {
|
||||
final StreamingOutput output = new StreamingOutput() {
|
||||
@Override
|
||||
public void write(OutputStream out) {
|
||||
try (FileInputStream in = new FileInputStream(file)) {
|
||||
byte[] buf = new byte[1024 * 1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) != -1) {
|
||||
try {
|
||||
out.write(buf, 0, len);
|
||||
out.flush();
|
||||
//System.out.println("---- wrote " + len + " bytes file ----");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("remote close connection");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new InternalServerErrorException(ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
Response.ResponseBuilder out = Response.ok(output)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, file.length());
|
||||
if (mimeType != null) {
|
||||
out.type(mimeType);
|
||||
}
|
||||
return out.build();
|
||||
|
||||
}
|
||||
|
||||
String[] ranges = range.split("=")[1].split("-");
|
||||
final long from = Long.parseLong(ranges[0]);
|
||||
|
||||
//System.out.println("request range : " + ranges.length);
|
||||
//Chunk media if the range upper bound is unspecified. Chrome, Opera sends "bytes=0-"
|
||||
long to = CHUNK_SIZE + from;
|
||||
if (ranges.length == 1) {
|
||||
to = file.length() - 1;
|
||||
} else {
|
||||
if (to >= file.length()) {
|
||||
to = (long) (file.length() - 1);
|
||||
}
|
||||
}
|
||||
final String responseRange = String.format("bytes %d-%d/%d", from, to, file.length());
|
||||
//System.out.println("responseRange : " + responseRange);
|
||||
final RandomAccessFile raf = new RandomAccessFile(file, "r");
|
||||
raf.seek(from);
|
||||
|
||||
final long len = to - from + 1;
|
||||
final MediaStreamer streamer = new MediaStreamer(len, raf);
|
||||
Response.ResponseBuilder out = Response.ok(streamer)
|
||||
.status(Response.Status.PARTIAL_CONTENT)
|
||||
.header("Accept-Ranges", "bytes")
|
||||
.header("Content-Range", responseRange)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, streamer.getLenth())
|
||||
.header(HttpHeaders.LAST_MODIFIED, new Date(file.lastModified()));
|
||||
if (mimeType != null) {
|
||||
out.type(mimeType);
|
||||
}
|
||||
return out.build();
|
||||
}
|
||||
|
||||
public static void undelete(Long id) throws Exception {
|
||||
SqlWrapper.unsetDelete(Data.class, id);
|
||||
}
|
||||
|
||||
}
|
56
src/org/kar/archidata/api/MediaStreamer.java
Normal file
56
src/org/kar/archidata/api/MediaStreamer.java
Normal file
@ -0,0 +1,56 @@
|
||||
package org.kar.archidata.api;
|
||||
|
||||
import javax.ws.rs.InternalServerErrorException;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
public class MediaStreamer implements StreamingOutput {
|
||||
private final int CHUNK_SIZE = 1024 * 1024; // 1MB chunks
|
||||
final byte[] buf = new byte[CHUNK_SIZE];
|
||||
private long length;
|
||||
private RandomAccessFile raf;
|
||||
|
||||
public MediaStreamer(long length, RandomAccessFile raf) throws IOException {
|
||||
//System.out.println("request stream of " + length / 1024 + " data");
|
||||
if (length<0) {
|
||||
throw new IOException("Wrong size of the file to stream: " + length);
|
||||
}
|
||||
this.length = length;
|
||||
this.raf = raf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(OutputStream outputStream) {
|
||||
try {
|
||||
while (length != 0) {
|
||||
int read = raf.read(buf, 0, buf.length > length ? (int) length : buf.length);
|
||||
try {
|
||||
outputStream.write(buf, 0, read);
|
||||
} catch (IOException ex) {
|
||||
System.out.println("remote close connection");
|
||||
break;
|
||||
}
|
||||
length -= read;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new InternalServerErrorException(ex);
|
||||
} catch (WebApplicationException ex) {
|
||||
throw new InternalServerErrorException(ex);
|
||||
} finally {
|
||||
try {
|
||||
raf.close();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
throw new InternalServerErrorException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long getLenth() {
|
||||
return length;
|
||||
}
|
||||
|
||||
}
|
@ -3,30 +3,29 @@ package org.kar.archidata.model;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class Data {
|
||||
public Long id;
|
||||
public boolean deleted;
|
||||
import org.kar.archidata.annotation.SQLComment;
|
||||
import org.kar.archidata.annotation.SQLIfNotExists;
|
||||
import org.kar.archidata.annotation.SQLLimitSize;
|
||||
import org.kar.archidata.annotation.SQLNotNull;
|
||||
import org.kar.archidata.annotation.SQLTableName;
|
||||
import org.kar.archidata.model.GenericTable;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
|
||||
@SQLTableName ("data")
|
||||
@SQLIfNotExists
|
||||
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
|
||||
public class Data extends GenericTable {
|
||||
|
||||
@SQLNotNull
|
||||
@SQLLimitSize(128)
|
||||
@SQLComment("Sha512 of the data")
|
||||
public String sha512;
|
||||
@SQLNotNull
|
||||
@SQLLimitSize(128)
|
||||
@SQLComment("Mime -type of the media")
|
||||
public String mimeType;
|
||||
@SQLNotNull
|
||||
@SQLComment("Size in Byte of the data")
|
||||
public Long size;
|
||||
|
||||
public Data() {
|
||||
|
||||
}
|
||||
|
||||
public Data(ResultSet rs) {
|
||||
int iii = 1;
|
||||
try {
|
||||
this.id = rs.getLong(iii++);
|
||||
this.deleted = rs.getBoolean(iii++);
|
||||
this.sha512 = rs.getString(iii++);
|
||||
this.mimeType = rs.getString(iii++);
|
||||
this.size = rs.getLong(iii++);
|
||||
if (rs.wasNull()) {
|
||||
this.size = null;
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,12 +30,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
@SQLTableName ("user")
|
||||
@SQLIfNotExists
|
||||
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
|
||||
public class User {
|
||||
@SQLAutoIncrement // Add AUTO_INCREMENT modifier
|
||||
@SQLPrimaryKey // Create a PRIMARY KEY based on this field
|
||||
@SQLNotNull
|
||||
@SQLComment("Primary key of the base")
|
||||
public Long id = null;
|
||||
public class User extends GenericTable {
|
||||
@SQLLimitSize(128)
|
||||
public String login = null;
|
||||
|
||||
|
@ -1,73 +0,0 @@
|
||||
package org.kar.archidata.model;
|
||||
|
||||
/*
|
||||
CREATE TABLE `user` (
|
||||
`id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY,
|
||||
`login` varchar(128) COLLATE 'utf8_general_ci' NOT NULL COMMENT 'login of the user',
|
||||
`password` varchar(128) COLLATE 'latin1_bin' NOT NULL COMMENT 'password of the user hashed (sha512)',
|
||||
`email` varchar(512) COLLATE 'utf8_general_ci' NOT NULL COMMENT 'email of the user',
|
||||
`emailValidate` bigint COMMENT 'date of the email validation',
|
||||
`newEmail` varchar(512) COLLATE 'utf8_general_ci' COMMENT 'email of the user if he want to change',
|
||||
`authorisationLevel` enum("REMOVED", "USER", "ADMIN") NOT NULL COMMENT 'user level of authorization'
|
||||
) AUTO_INCREMENT=10;
|
||||
|
||||
*/
|
||||
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class UserSmall {
|
||||
public long id;
|
||||
public String login;
|
||||
public String email;
|
||||
public State authorisationLevel;
|
||||
|
||||
public UserSmall() {
|
||||
}
|
||||
|
||||
public UserSmall(long id, String login, String email, State authorisationLevel) {
|
||||
this.id = id;
|
||||
this.login = login;
|
||||
this.email = email;
|
||||
this.authorisationLevel = authorisationLevel;
|
||||
}
|
||||
|
||||
public UserSmall(ResultSet rs) {
|
||||
int iii = 1;
|
||||
try {
|
||||
this.id = rs.getLong(iii++);
|
||||
this.login = rs.getString(iii++);
|
||||
this.email = rs.getString(iii++);
|
||||
this.authorisationLevel = State.valueOf(rs.getString(iii++));
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
/*
|
||||
public void serialize(ResultSet rs) {
|
||||
int iii = 1;
|
||||
try {
|
||||
this.id = rs.getLong(iii++);
|
||||
this.login = rs.getString(iii++);
|
||||
this.password = rs.getString(iii++);
|
||||
this.email = rs.getString(iii++);
|
||||
this.emailValidate = rs.getLong(iii++);
|
||||
this.newEmail = rs.getString(iii++);
|
||||
this.authorisationLevel = State.valueOf(rs.getString(iii++));
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserSmall{" +
|
||||
"id='" + id + '\'' +
|
||||
", login='" + login + '\'' +
|
||||
", email='" + email + '\'' +
|
||||
", authorisationLevel=" + authorisationLevel +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -73,43 +73,23 @@ public class DataTools {
|
||||
}
|
||||
|
||||
public static Data getWithSha512(String sha512) {
|
||||
System.out.println("find sha512 = " + sha512);
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
String query = "SELECT `id`, `deleted`, `sha512`, `mime_type`, `size` FROM `data` WHERE `sha512` = ?";
|
||||
try {
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query);
|
||||
ps.setString(1, sha512);
|
||||
ResultSet rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
Data out = new Data(rs);
|
||||
entry.disconnect();
|
||||
return out;
|
||||
}
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
entry.disconnect();
|
||||
return null;
|
||||
|
||||
try {
|
||||
return SqlWrapper.getWhere(Data.class, "sha512", "=", sha512);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Data getWithId(long id) {
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
String query = "SELECT `id`, `deleted`, `sha512`, `mime_type`, `size` FROM `data` WHERE `deleted` = false AND `id` = ?";
|
||||
try {
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query);
|
||||
ps.setLong(1, id);
|
||||
ResultSet rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
Data out = new Data(rs);
|
||||
entry.disconnect();
|
||||
return out;
|
||||
}
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
entry.disconnect();
|
||||
return null;
|
||||
try {
|
||||
return SqlWrapper.getWhere(Data.class, "deleted", "=", false, "id", "=", id);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Data createNewData(long tmpUID, String originalFileName, String sha512) throws IOException, SQLException {
|
||||
@ -141,41 +121,20 @@ public class DataTools {
|
||||
}
|
||||
String tmpPath = getTmpFileInData(tmpUID);
|
||||
long fileSize = Files.size(Paths.get(tmpPath));
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
long uniqueSQLID = -1;
|
||||
Data out = new Data();;
|
||||
try {
|
||||
// prepare the request:
|
||||
String query = "INSERT INTO `data` (`sha512`, `mime_type`, `size`, `original_name`) VALUES (?, ?, ?, ?)";
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query,
|
||||
Statement.RETURN_GENERATED_KEYS);
|
||||
int iii = 1;
|
||||
ps.setString(iii++, sha512);
|
||||
ps.setString(iii++, mimeType);
|
||||
ps.setLong(iii++, fileSize);
|
||||
ps.setString(iii++, originalFileName);
|
||||
// execute the request
|
||||
int affectedRows = ps.executeUpdate();
|
||||
if (affectedRows == 0) {
|
||||
throw new SQLException("Creating data failed, no rows affected.");
|
||||
}
|
||||
// retreive uid inserted
|
||||
try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
|
||||
if (generatedKeys.next()) {
|
||||
uniqueSQLID = generatedKeys.getLong(1);
|
||||
} else {
|
||||
throw new SQLException("Creating user failed, no ID obtained (1).");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Can not get the UID key inserted ... ");
|
||||
ex.printStackTrace();
|
||||
throw new SQLException("Creating user failed, no ID obtained (2).");
|
||||
}
|
||||
out.sha512 = sha512;
|
||||
out.mimeType = mimeType;
|
||||
out.size = fileSize;
|
||||
out = SqlWrapper.insert(out);
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
entry.disconnect();
|
||||
System.out.println("Add Data raw done. uid data=" + uniqueSQLID);
|
||||
Data out = getWithId(uniqueSQLID);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
String mediaPath = getFileData(out.id);
|
||||
System.out.println("src = " + tmpPath);
|
||||
@ -183,22 +142,17 @@ public class DataTools {
|
||||
Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE);
|
||||
|
||||
System.out.println("Move done");
|
||||
// all is done the file is corectly installed...
|
||||
|
||||
// all is done the file is correctly installed...
|
||||
return out;
|
||||
}
|
||||
|
||||
public static void undelete(Long id) {
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
String query = "UPDATE `data` SET `deleted` = false WHERE `id` = ?";
|
||||
try {
|
||||
PreparedStatement ps = entry.connection.prepareStatement(query);
|
||||
ps.setLong(1, id);
|
||||
ps.execute();
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
entry.disconnect();
|
||||
try {
|
||||
SqlWrapper.unsetDelete(Data.class, id);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String saveTemporaryFile(InputStream uploadedInputStream, long idData) {
|
||||
|
Loading…
Reference in New Issue
Block a user