Loading local files into a Babylonjs scene directly - babylonjs

Babaylonjs is able to load babylon, gltf, obj and files into a scene.
How to load a model, and its accompanying files like images for textures (or e.g. bin file for gltf, mtl file for obj), file selected from a file select dialog by an html input type=file? Note the accompanying files can be in arbitrary directories beside the main model file.
Note: Babylonjs Assets Manager and SceneLoader methods all http requests from a server. They are not what I look for. Also http posting a file to remote server then using babylonjs methods I have mentioned to http request and load into scene is not what am I looking for here.

Okay have you tried this ?
You import your file by using an input file.
Then you get your file from the input const myFile = target.file[0]
Then you create an url with it and use this URL to import your object on the scene
const url = URL.createObjectURL(myFile);
BABYLON.SceneLoader.ImportMeshAsync(
"",
url,
"",
scene,
null,
fileExtension
);
It enables you to use a an input file without knowing precisly where it is located in your computer and use the Babylon methods based on request to import it.

I recommend you to check code of BabylonJS sandbox which supports model import from local file system: https://sandbox.babylonjs.com/
In this example you have two ways to import a local model to the scene:
drag model to the canvas
click on Upload button on the right bottom corner. File select
dialog will be opened. You can choose multiple files
View 268-291 code lines of the script used in BabylonJS sandbox (https://sandbox.babylonjs.com/index.js):
filesInput = new BABYLON.FilesInput(engine, null, sceneLoaded, null, null, null, startProcessingFiles, null, sceneError);
filesInput.onProcessFileCallback = (function(file, name, extension) {
if (filesInput._filesToLoad && filesInput._filesToLoad.length === 1 && extension) {
if (extension.toLowerCase() === "dds" || extension.toLowerCase() === "env") {
BABYLON.FilesInput.FilesToLoad[name] = file;
skyboxPath = "file:" + file.correctName;
return false;
}
}
return true;
}).bind(this);
filesInput.monitorElementForDragNDrop(canvas);
htmlInput.addEventListener('change', function(event) {
// Handling data transfer via drag'n'drop
if (event && event.dataTransfer && event.dataTransfer.files) {
filesToLoad = event.dataTransfer.files;
}
// Handling files from input files
if (event && event.target && event.target.files) {
filesToLoad = event.target.files;
}
filesInput.loadFiles(event);
}, false);
As you can see there is used a BabylonJS class FilesInput. More info about FilesInput class: https://doc.babylonjs.com/api/classes/babylon.filesinput

Related

How can I check the actual URL path in Next.js 13?

In head.tsx (I am using AppDir) of each page of my site, I pass canonicalPath (among others) to a server component that renders all <meta> tags.
I want to make a simple development only validation that the canonicalPath supplied is actually the same as the actual current path in the browser and throw an Error if it isn't. I cannot figure out how to do this:
Serverside, the only thing I found is headers() which for some reason contains the hostname but not the path. And besides, it's a dynamic function and will force dynamic rendering.
So I created a client component:
"use client";
import { usePathname } from "next/navigation";
import { LayoutHeadProps } from "./layout-head";
export default function LayoutHeadClient(props: LayoutHeadProps): React.ReactNode {
const path = usePathname();
if (process.env.NODE_ENV === "development") {
if (props.canonicalPath !== path) {
throw new Error(`Actual path does not correspond to canonical path: "${path}" != "${props.canonicalPath}"`);
}
}
return <></>;
}
But this does not work either:
Warning: Cannot update a component (`HotReload`) while rendering a different component (`LayoutHeadClient`). To locate the bad setState() call inside `LayoutHeadClient`
and then it throws the Error because at the time it is evaluated, canonicalPath still evaluates to the previous page. When I later look it up in the source code, it is correct.

Download a static file with strict name via Nginx [duplicate]

I'm writing a web application that, among other things, allows users to upload files to my server. In order to prevent name clashes and to organize the files, I rename them once they are put on my server. By keeping track of the original file name I can communicate with the file's owner without them ever knowing I changed the file name on the back end. That is, until they go do download the file. In that case they're prompted to download a file with a unfamiliar name.
My question is, is there any way to specify the name of a file to be downloaded using just HTML? So a user uploads a file named 'abc.txt' and I rename it to 'xyz.txt', but when they download it I want the browser to save the file as 'abc.txt' by default. If this isn't possible with just HTML, is there any way to do it?
When they click a button to download the file, you can add the HTML5 attribute download where you can set the default filename.
That's what I did, when I created a xlsx file and the browser want to save it as zip file.
Download
Download Export
Can't find a way in HTML. I think you'll need a server-side script which will output a content-disposition header. In php this is done like this:
header('Content-Disposition: attachment; filename="downloaded.pdf"');
if you wish to provide a default filename, but not automatic download, this seems to work.
header('Content-Disposition: inline; filename="filetodownload.jpg"');
In fact, it is the server that is directly serving your files, so you have no way to interact with it from HTML, as HTML is not involved at all.
just need to use HTML5 a tag download attribute
codepen live demo
https://codepen.io/xgqfrms/full/GyEGzG/
my screen shortcut.
update answer
whether a file is downloadable depends on the server's response config, such as Content-Type, Content-Disposition;
download file's extensions are optional, depending on the server's config, too.
'Content-Type': 'application/octet-stream',
// it means unknown binary file,
// browsers usually don't execute it, or even ask if it should be executed.
'Content-Disposition': `attachment; filename=server_filename.filetype`,
// if the header specifies a filename,
// it takes priority over a filename specified in the download attribute.
download blob url file
function generatorBlobVideo(url, type, dom, link) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function(res) {
// console.log('res =', res);
var blob = new Blob(
[xhr.response],
{'type' : type},
);
// create blob url
var urlBlob = URL.createObjectURL(blob);
dom.src = urlBlob;
// download file using `a` tag
link.href = urlBlob;
};
xhr.send();
}
(function() {
var type = 'image/png';
var url = 'https://cdn.xgqfrms.xyz/logo/icon.png';
var dom = document.querySelector('#img');
var link = document.querySelector('#img-link');
generatorBlobVideo(url, type, dom, link);
})();
https://cdn.xgqfrms.xyz/HTML5/Blob/index.html
refs
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#download
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#important_mime_types_for_web_developers
Sometimes #Mephiztopheles answer won't work on blob storages and some browsers.
For this you need to use a custom function to convert the file to blob and download it
const coverntFiletoBlobAndDownload = async (file, name) => {
const blob = await fetch(file).then(r => r.blob())
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.style.display = 'none'
a.href = url
a.download = name // add custom extension here
document.body.appendChild(a)
a.click()
window.URL.revokeObjectURL(url)
}
Same code as #Hillkim Henry but with a.remove() improvement
This forces the document to remove the a tag from the body and avoid multiple elements
const coverntFiletoBlobAndDownload = async (file, name) => {
const blob = await fetch(file).then(r => r.blob())
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.style.display = 'none'
a.href = url
a.download = name // add custom extension here
document.body.appendChild(a)
a.click()
window.URL.revokeObjectURL(url)
// Remove "a" tag from the body
a.remove()
}
Well, #Palantir's answer is, for me, the most correct way!
If you plan to use that with multiple files, then i suggest you to use (or make one) PHP Download Manager.
BUT, if you want to make that to one or two files, I will suggest you the mod_rewrite option:
You have to create or edit your .htaccess file on htdocs folder and add this:
RewriteEngine on
RewriteRule ^abc\.txt$ xyz.txt
With this code, users will download xyz.txt data with the name abc.txt
NOTE: Verify if you have already the "RewriteEngine on " on your file, if yes, add only the second for each file you wish to redirect.
Good Luck ;)
(Sorry for my english)

Can't get the names of the files that exist in a specific directory using File or InputStream [duplicate]

I have a resources folder/package in the root of my project, I "don't" want to load a certain File. If I wanted to load a certain File, I would use class.getResourceAsStream and I would be fine!! What I actually want to do is to load a "Folder" within the resources folder, loop on the Files inside that Folder and get a Stream to each file and read in the content... Assume that the File names are not determined before runtime... What should I do? Is there a way to get a list of the files inside a Folder in your jar File?
Notice that the Jar file with the resources is the same jar file from which the code is being run...
Finally, I found the solution:
final String path = "sample/folder";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
if(jarFile.isFile()) { // Run with JAR file
final JarFile jar = new JarFile(jarFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while(entries.hasMoreElements()) {
final String name = entries.nextElement().getName();
if (name.startsWith(path + "/")) { //filter according to the path
System.out.println(name);
}
}
jar.close();
} else { // Run with IDE
final URL url = Launcher.class.getResource("/" + path);
if (url != null) {
try {
final File apps = new File(url.toURI());
for (File app : apps.listFiles()) {
System.out.println(app);
}
} catch (URISyntaxException ex) {
// never happens
}
}
}
The second block just work when you run the application on IDE (not with jar file), You can remove it if you don't like that.
Try the following.
Make the resource path "<PathRelativeToThisClassFile>/<ResourceDirectory>" E.g. if your class path is com.abc.package.MyClass and your resoure files are within src/com/abc/package/resources/:
URL url = MyClass.class.getResource("resources/");
if (url == null) {
// error - missing folder
} else {
File dir = new File(url.toURI());
for (File nextFile : dir.listFiles()) {
// Do something with nextFile
}
}
You can also use
URL url = MyClass.class.getResource("/com/abc/package/resources/");
The following code returns the wanted "folder" as Path regardless of if it is inside a jar or not.
private Path getFolderPath() throws URISyntaxException, IOException {
URI uri = getClass().getClassLoader().getResource("folder").toURI();
if ("jar".equals(uri.getScheme())) {
FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
return fileSystem.getPath("path/to/folder/inside/jar");
} else {
return Paths.get(uri);
}
}
Requires java 7+.
I know this is many years ago . But just for other people come across this topic.
What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir. After that you can concat the dir path with each file name and call getResourceAsStream for each file in a loop.
I had the same problem at hands while i was attempting to load some hadoop configurations from resources packed in the jar... on both the IDE and on jar (release version).
I found java.nio.file.DirectoryStream to work the best to iterate over directory contents over both local filesystem and jar.
String fooFolder = "/foo/folder";
....
ClassLoader classLoader = foofClass.class.getClassLoader();
try {
uri = classLoader.getResource(fooFolder).toURI();
} catch (URISyntaxException e) {
throw new FooException(e.getMessage());
} catch (NullPointerException e){
throw new FooException(e.getMessage());
}
if(uri == null){
throw new FooException("something is wrong directory or files missing");
}
/** i want to know if i am inside the jar or working on the IDE*/
if(uri.getScheme().contains("jar")){
/** jar case */
try{
URL jar = FooClass.class.getProtectionDomain().getCodeSource().getLocation();
//jar.toString() begins with file:
//i want to trim it out...
Path jarFile = Paths.get(jar.toString().substring("file:".length()));
FileSystem fs = FileSystems.newFileSystem(jarFile, null);
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(fs.getPath(fooFolder));
for(Path p: directoryStream){
InputStream is = FooClass.class.getResourceAsStream(p.toString()) ;
performFooOverInputStream(is);
/** your logic here **/
}
}catch(IOException e) {
throw new FooException(e.getMessage());
}
}
else{
/** IDE case */
Path path = Paths.get(uri);
try {
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
for(Path p : directoryStream){
InputStream is = new FileInputStream(p.toFile());
performFooOverInputStream(is);
}
} catch (IOException _e) {
throw new FooException(_e.getMessage());
}
}
Another solution, you can do it using ResourceLoader like this:
import org.springframework.core.io.Resource;
import org.apache.commons.io.FileUtils;
#Autowire
private ResourceLoader resourceLoader;
...
Resource resource = resourceLoader.getResource("classpath:/path/to/you/dir");
File file = resource.getFile();
Iterator<File> fi = FileUtils.iterateFiles(file, null, true);
while(fi.hasNext()) {
load(fi.next())
}
If you are using Spring you can use org.springframework.core.io.support.PathMatchingResourcePatternResolver and deal with Resource objects rather than files. This works when running inside and outside of a Jar file.
PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver();
Resource[] resources = r.getResources("/myfolder/*");
Then you can access the data using getInputStream and the filename from getFilename.
Note that it will still fail if you try to use the getFile while running from a Jar.
As the other answers point out, once the resources are inside a jar file, things get really ugly. In our case, this solution:
https://stackoverflow.com/a/13227570/516188
works very well in the tests (since when the tests are run the code is not packed in a jar file), but doesn't work when the app actually runs normally. So what I've done is... I hardcode the list of the files in the app, but I have a test which reads the actual list from disk (can do it since that works in tests) and fails if the actual list doesn't match with the list the app returns.
That way I have simple code in my app (no tricks), and I'm sure I didn't forget to add a new entry in the list thanks to the test.
Below code gets .yaml files from a custom resource directory.
ClassLoader classLoader = this.getClass().getClassLoader();
URI uri = classLoader.getResource(directoryPath).toURI();
if("jar".equalsIgnoreCase(uri.getScheme())){
Pattern pattern = Pattern.compile("^.+" +"/classes/" + directoryPath + "/.+.yaml$");
log.debug("pattern {} ", pattern.pattern());
ApplicationHome home = new ApplicationHome(SomeApplication.class);
JarFile file = new JarFile(home.getSource());
Enumeration<JarEntry> jarEntries = file.entries() ;
while(jarEntries.hasMoreElements()){
JarEntry entry = jarEntries.nextElement();
Matcher matcher = pattern.matcher(entry.getName());
if(matcher.find()){
InputStream in =
file.getInputStream(entry);
//work on the stream
}
}
}else{
//When Spring boot application executed through Non-Jar strategy like through IDE or as a War.
String path = uri.getPath();
File[] files = new File(path).listFiles();
for(File file: files){
if(file != null){
try {
InputStream is = new FileInputStream(file);
//work on stream
} catch (Exception e) {
log.error("Exception while parsing file yaml file {} : {} " , file.getAbsolutePath(), e.getMessage());
}
}else{
log.warn("File Object is null while parsing yaml file");
}
}
}
Took me 2-3 days to get this working, in order to have the same url that work for both Jar or in local, the url (or path) needs to be a relative path from the repository root.
..meaning, the location of your file or folder from your src folder.
could be "/main/resources/your-folder/" or "/client/notes/somefile.md"
Whatever it is, in order for your JAR file to find it, the url must be a relative path from the repository root.
it must be "src/main/resources/your-folder/" or "src/client/notes/somefile.md"
Now you get the drill, and luckily for Intellij Idea users, you can get the correct path with a right-click on the folder or file -> copy Path/Reference.. -> Path From Repository Root (this is it)
Last, paste it and do your thing.
Simple ... use OSGi. In OSGi you can iterate over your Bundle's entries with findEntries and findPaths.
Inside my jar file I had a folder called Upload, this folder had three other text files inside it and I needed to have an exactly the same folder and files outside of the jar file, I used the code below:
URL inputUrl = getClass().getResource("/upload/blabla1.txt");
File dest1 = new File("upload/blabla1.txt");
FileUtils.copyURLToFile(inputUrl, dest1);
URL inputUrl2 = getClass().getResource("/upload/blabla2.txt");
File dest2 = new File("upload/blabla2.txt");
FileUtils.copyURLToFile(inputUrl2, dest2);
URL inputUrl3 = getClass().getResource("/upload/blabla3.txt");
File dest3 = new File("upload/Bblabla3.txt");
FileUtils.copyURLToFile(inputUrl3, dest3);

openWithDefaultApplication fails on files in application folder

I'll ONLY recieve an "Error #3000: Illegal path name" if I try to open a file which is placed inside the app-folder of the air. If the file is somewhere else outside of the app-folder it works.
private var file:File = File.documentsDirectory;
public function download():void{
var pdfFilter:FileFilter = new FileFilter("PDF Files", "*.pdf");
file.browseForOpen("Open", [pdfFilter]);
file.addEventListener(Event.SELECT, fileSelected);
}
private function fileSelected(e:Event):void
{
var destination:File = File.applicationDirectory
destination = destination.resolvePath("test.pdf");
/*
//This works, also if the file to copy is placed inside the appfolder
file.copyTo(destination, true);
*/
/*This Throws me an Error #3000, but ONLY if the file is located in
the App folder*/
file.openWithDefaultApplication();
}
When i try to get the same file and copy it to another place it's doing fine.
Why that? Something special to do if i wanna open files which are inside the appfolder?
It also don't work in debug mode - bin-debug.
Regards, Temo
After reading the document a few times i saw that this is not possible (it's not a bug, it's a feature!?!)
Opening files with the default system application
You cannot use the openWithDefaultApplication() method with files located in the application directory.
So I do this instead:
file.copyTo(tempFile);
tempFile.openWithDefaultApplication();
Not so nice, but it works.

Flex: Loading assets into externally loaded modules

So, I have Flex project that loads a Module using the ModuleManager - not the module loader. The problem that I'm having is that to load an external asset (like a video or image) the path to load that asset has to be relative to the Module swf...not relative to the swf that loaded the module.
The question is - How can I load an asset into a loaded module using a path relative to the parent swf, not the module swf?
Arg! So in digging through the SWFLoader Class I found this chunk of code in private function loadContent:
// make relative paths relative to the SWF loading it, not the top-level SWF
if (!(url.indexOf(":") > -1 || url.indexOf("/") == 0 || url.indexOf("\\") == 0))
{
var rootURL:String;
if (SystemManagerGlobals.bootstrapLoaderInfoURL != null && SystemManagerGlobals.bootstrapLoaderInfoURL != "")
rootURL = SystemManagerGlobals.bootstrapLoaderInfoURL;
else if (root)
rootURL = LoaderUtil.normalizeURL(root.loaderInfo);
else if (systemManager)
rootURL = LoaderUtil.normalizeURL(DisplayObject(systemManager).loaderInfo);
if (rootURL)
{
var lastIndex:int = Math.max(rootURL.lastIndexOf("\\"), rootURL.lastIndexOf("/"));
if (lastIndex != -1)
url = rootURL.substr(0, lastIndex + 1) + url;
}
}
}
So apparently, Adobe has gone through the extra effort to make images load in the actual swf and not the top level swf (with no flag to choose otherwise...), so I guess I should submit a feature request to have some sort of "load relative to swf" flag, edit the SWFLoader directly, or maybe I should have everything relative to the individual swf and not the top level...any suggestions?
You can import mx.core.Application and then use Application.application.url to get the path of the host application in your module and use that as the basis for building the URLs.
For help in dealing with URLs, see the URLUtil class in the standard Flex libraries and the URI class in the as3corelib project.
You can use this.url in the module and use this as a baseURL.
var urlParts:Array = this.url.split("/");
urlParts.pop();
baseURL = urlParts.join("/");
Alert.show(baseURL);
and use {baseURL + "/location/file.ext"} instead of /location/file.ext

Resources