I have a function in an sdk where it strictly uses file from asset folder. I want to use the file from online. When I am passing the filename as example.mbtiles it is searching for the file is Asset folder and if found the app working fine. But when I am trying to get the file from a url such as www.myurl.com/example.mbtiles its taking all the url as string and finding the file in Asset folder which makes the app not working. Here is the function
private File getFile(String url, final Context context) {
if (context != null) {
//we assume asset here
AssetManager am = context.getAssets();
InputStream inputStream;
try {
inputStream = am.open(url);
final File mbTilesDir;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| (!Environment.isExternalStorageRemovable())) {
mbTilesDir = new File(context.getExternalFilesDir(null), url);
} else {
mbTilesDir = new File(context.getFilesDir(), url);
}
return createFileFromInputStream(inputStream, mbTilesDir.getPath());
} catch (IOException e) {
Log.e(TAG, "MBTiles file not found in assets: " + e.toString());
return null;
}
}
try {
return new File(url);
} catch (Exception e) {
Log.e(TAG, "can't load MBTiles: " + e.toString());
return null;
}
}
How can I get the file from online url instead of local asset folder? what changes I need to do in this code? I also want to know, can I override this function in my MainActivity?
Related
This spring app performs simple file upload,
here's the controller class
#Override
public String fileUpload(MultipartFile file) {
try{
// save uploaded image to images folder in root dir
Files.write(Paths.get("images/"+ file.getOriginalFilename()), file.getBytes());
// perform some tasks on image
return "";
} catch (IOException ioException) {
return "File upload has failed.";
} finally {
Files.delete(Paths.get("images/" + file.getOriginalFilename()));
}
}
but when i build jar and runs, it throws IOException saying,
java.nio.file.NoSuchFileException: images\8c9.jpeg.
So my question is how can i add the images folder inside the jar executable itself.
Thanks.
You should provide a full path for the images folder, or save in java.io.tmpdir creating the image folder first.
But, in my opinion you should configure your upload folder from a config file for flexibility. Take a look at this.
app:
profile-image:
upload-dir: C:\\projs\\web\\profile_image
file-types: jpg, JPG, png, PNG
width-height: 360, 360
max-size: 5242880
In your service or controller, do whatever you like, may be validate image type, size etc and process it as you like. For instance, if you want thumbnails(or avatar..).
In your controller or service class, get the directory:
#Value("${app.image-upload-dir:../images}")
private String imageUploadDir;
Finally,
public static Path uploadFileToPath(String fullFileName, String uploadDir, byte[] filecontent) throws IOException {
Path fileOut = null;
try{
Path fileAbsolutePath = Paths.get(StringUtils.join(uploadDir, File.separatorChar, fullFileName));
fileOut = Files.write(fileAbsolutePath, filecontent);
}catch (Exception e) {
throw e;
}
return fileOut; //full path of the file
}
For your question in the comment: You can use java.io.File.deleteOnExit() method, which deletes the file or directory defined by the abstract path name when the virtual machine terminates. TAKE A GOOD CARE THOUGH, it might leave some files if not handled properly.
try (ByteArrayOutputStream output = new ByteArrayOutputStream();){
URL fileUrl = new URL(url);
String tempDir = System.getProperty("java.io.tmpdir");
String path = tempDir + new Date().getTime() + ".jpg"; // note file extension
java.io.File file = new java.io.File(path);
file.deleteOnExit();
inputStream = fileUrl.openStream();
ByteStreams.copy(inputStream, output); // ByteStreams - Guava
outputStream = new FileOutputStream(file);
output.writeTo(outputStream);
outputStream.flush();
return file;
} catch (Exception e) {
throw e;
} finally {
try {
if(inputStream != null) {
inputStream.close();
}
if(outputStream != null) {
outputStream.close();
}
} catch(Exception e){
//skip
}
}
I have the strangest behavior using the JCIFS SmbFile.renameTo() method. When I execute the code below it should move the network file from test1 to test2, but instead it creates a folder in test2 called test.xml and throws the following error "Cannot create a file when that file already exists..." I can't figure it out. Why is this method doing this?
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication (sDomain,
sUsername, sPassword);
SmbFile smbFromFile = new SmbFile("smb://test1/test.xml", auth);
SmbFile smbToFile = new SmbFile("smb://test2/test.xml", auth);
smbFromFile.renameTo(smbToFile);
There's an interesting difference between copyTo(SmbFile) and renameTo(SmbFile) - only one of them says This file and the destination file do not need to be on the same host. As renameTo(SmbFile) does not say that, I can only assume you should use copyTo and then delete() the original.
SmbFile smbFromFile = new SmbFile("smb://test1/test.xml", auth);
SmbFile smbToFile = new SmbFile("smb://test2/test.xml", auth);
// smbFromFile.renameTo(smbToFile);
smbFromFile.copyTo(smbToFile);
smbFromFile.delete();
There are two possible Scenarios:
1.) The file needs to be moved on the same server ( That is, the authentication details for Input folder and Output folder are same).
Use renameTo() method.
public boolean moveFile(SmbFile file) {
log.info("{"Started Archiving or Moving the file");
String targetFilePath = this.archiveDir + file.getName(); //Path where we need to move that file.
try {
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", userId, userPassword);
log.info("targetFilePath: {} , currentFile : {}",targetFilePath, file);
SmbFile targetFile = new SmbFile(targetFilePath, auth);
//authenticate the SmbFile
try {
file.renameTo(targetFile); //User renameTo method for same server
log.info("Archived File : {} to: {}", file.getName(),
targetFile.getName());
return true;
} catch (SmbException e) {
log.error("Unable to Archive File: {}", file.getName());
return false;
}
} catch (MalformedURLException e) {
log.error("Connection failed to Server Drive: {}", targetFilePath);
}
return false;
}
2.) The file needs to be moved on Different server ( That is, the authentication details for Input folder and Output folder are NOT same).
Use copyTo() method.
Here I will suggest, You can firstly authenticate the first server on which file is present, And check if the File exists, If it is existing then add that in a list :
public List<SmbFile> xmlFiles = new ArrayList<>(); //Here we will add all the files which are existing.
public boolean isFileExists() throws MalformedURLException, SmbException {
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("",
userID, userPassword); //authenticating input folder.
SmbFile smbFile = new SmbFile(inputFolder, auth);
SmbFile[] smbFiles = smbFile.listFiles();
boolean isFilePresent = false;
if (smbFiles.length > 0) {
for (SmbFile file : smbFiles) {
if (file.getName().toLowerCase(Locale.ENGLISH)
.contains(AppConstant.FILE_NAME.toLowerCase(Locale.ENGLISH))) {
xmlFiles.add(file);
isFilePresent = true;
}
}
}
if (isPlanFilePresent) {
log.info("Number of files present on Server: {}",smbFiles.length);
return true;
}
return false;
}
This will give you the files in the list. Go ahead to copy it to another server. Note that you need to authenticate here for the output Folder only.
public boolean moveFile(SmbFile file) {
log.info("Started Moving or Archiving the file");
String toFilePath = this.outputFolder + file.getName(); //path where you need to copy the file from input folder.
try {
NtlmPasswordAuthentication auth1 = new NtlmPasswordAuthentication("", outputFolderUserId, outputFolderPassword); //authenticating output folder
log.info("targetFilePath: {} and currentFile : {}", toFilePath, file);
SmbFile targetFile = new SmbFile(toFilePath, auth1);
try {
file.copyTo(targetFile);
file.delete(); //delete the file which we copied at our desired server
log.info("Archived File : {} to: {}", file.getName(), targetFile.getName());
return true;
} catch (SmbException e) {
log.error("Unable to Archive File: {}", file.getName());
return false;
}
} catch (MalformedURLException e) {
log.error("Connection failed to Server Drive: {}", toFilePath);
}
return false;
}
Happy to Help :)
I try to use the official Dropbox API for uploading a zip file to my account. My project is a desktop application (standard Java). My code looks like this:
public void uploadZipFile(File file) throws Exception {
FileInputStream fis = new FileInputStream(file);
try {
getClient(accessToken).uploadFile("/" + file.getName(), DbxWriteMode.add(), file.length(), fis);
} finally {
fis.close();
}
}
private DbxClient getClient(String accessToken) {
DbxRequestConfig dbxRequestConfig = new DbxRequestConfig(Constants.APP_NAME, Locale.getDefault().toString());
return new DbxClient(dbxRequestConfig, accessToken);
}
And I call it:
File zipFile = new File("C:\\Test\\MyFile.zip");
try {
uploadZipFile(zipFile);
} catch (Exception e) {
e.printStackTrace();
}
The file is transferred without any problems but then I want to delete the file after synchronization:
File zipFile = new File("C:\\Test\\MyFile.zip");
try {
uploadZipFile(zipFile);
System.out.println(zipFile.delete());
} catch (Exception e) {
e.printStackTrace();
}
The file is transferred successfully again, but the file still exists in the local file system and the delete method returns false.
there is a text file that an application produces, I would like to take that file and read it as strings in my application. How can I achieve that, any help would be grateful. Both applications are my applications so I can get the permissions.
Thank you!
This is possible using the standard android-storage, where all the user's files are stored too:
All you need to do is to access the same file and the same path in both applications, so e.g.:
String fileName = Environment.getExternalStorageDirectory().getPath() + "myFolderForBothApplications/myFileNameForBothApplications.txt";
Where myFolderForBothApplications and myFileNameForBothApplications can be replaced by your folder/filename, but this needs to be the same name in both applications.
Environment.getExternalStorageDirectory() returns a File-Object to the common, usable file-directory of the device, the same folder the user can see too.
By calling the getPath() method, a String representing the path to this storage is returned, so you can add your folder/filenames afterwards.
So a full code example would be:
String path = Environment.getExternalStorageDirectory().getPath() + "myFolderForBothApplications/";
String pathWithFile = path + "myFileNameForBothApplications.txt";
File dir = new File(path);
if(!dir.exists()) { //If the directory is not created yet
if(!dir.mkdirs()) { //try to create the directories to the given path, the method returns false if the directories could not be created
//Make some error-output here
return;
}
}
File file = new File(pathWithFile);
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
//File couldn't be created
return;
}
Afterwards, you can write in the file or read from the file as provided e.g. in this answer.
Note that the file stored like this is visible for the user and my be edited / deleted by the user.
Also note what the JavaDoc for the getExternalStorageDirectory() says:
Return the primary external storage directory. This directory may not currently be accessible if it has been mounted by the user on their computer, has been removed from the device, or some other problem has happened. You can determine its current state with getExternalStorageState().
I do not know if this is the best/safest way to fix your problem, but it should work.
You can save the text file from your assets folder to anywhere in the sdcard, then you can read the file from the other application.
This method uses the getExternalFilesDir, that returns the absolute path to the directory on the primary shared/external storage device where the application can place persistent files it owns. These files are internal to the applications, and not typically visible to the user as media.
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
if (files != null) for (String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
File outFile = new File(Environment.getExternalStorageDirectory(), filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
And to read:
File dir = Environment.getExternalStorageDirectory();
File yourFile = new File(dir, "path/to/the/file/inside/the/sdcard.ext");
I have successfully been able to save a file to my internal storage on android using the following code in java/android:
public void writeToFile(String filename) {
String code = getIntent().getStringExtra("code_full");
String fullCode = code;
try {
FileOutputStream fileOutputStream = openFileOutput(filename + ".cs", MODE_PRIVATE);
fileOutputStream.write(fullCode.getBytes());
fileOutputStream.close();
Toast.makeText(getApplicationContext(), "Saved as " + filename, Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I do not know where I can find the saved file in my android's folders (I am trying to find it on my PC with the phone plugged in.)
Anyone know where to find it?
If you saved a file to internal storage and want a String of the path to the file, you would do getFilesDir().getAbsolutePath().