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
Related
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)
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
How to change the installer path and add subfolder using qt installer framework.
Default output:
C:\Program Files (x86)\Subfolder
I want to path to example output.
Example output:
D:\Subfolder
C:\Desktop\Subfolder
C:\Documents\Subfolder
I know this is old but maybe is usefull for someone.
I changed a Qt Installer Framework example called dynamicpage (look in QtIfw examples dir), where the target directory is selected from a custom widget called targetwidgetui. To avoid the user write directly in the line edit I added in my file config/controllerscript.qs this code:
Controller.prototype.TargetDirectoryPageCallback = function()
{
currentPage.TargetDirectoryLineEdit.enabled = false;
}
I also added #ApplicationsDir#/MyAppFolder in config.xml so this is the default install path.
When the user change the destination folder I take the path and append "/MyAppFolder". To do this I changed a function in the dynamicpage example, in file installscript.qs. This is how my function look like now:
Component.prototype.chooseTarget = function () {
var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
if (widget != null) {
var newTarget = QFileDialog.getExistingDirectory("Choose your target directory.", widget
.targetDirectory.text);
if (newTarget != "")
{
newTarget += "/MyAppFolder"; // The same subfolder of TargetDir in config.xml
widget.targetDirectory.text = Dir.toNativeSparator(newTarget);
}
}
}
Using this you will append always your folder to the installation path.
In your config.xml file you can add
<TargetDir>*YOUR_PATH*/subfolder</TargetDir>
To install to a custom directory.
From Qt Installer Framework documentation:
TargetDir
Default target directory for installation. On Linux, this is usually the user's home directory.
Note that you can use predefined variables like #ApplicationsDir# or #DesktopDir# as stated here.
Is it possible to save an image from an url in the assets folder?
void DataPacking::createAndSaveImage(QString argSavingFilePath,
QByteArray argDataLoaded) {
m_file = new QFile;
m_file->setFileName(argSavingFilePath);
m_file->open(QIODevice::WriteOnly);
m_file->write(argDataLoaded);
m_file->close();
m_file->~QFile();
}
m_savingFilePath = QDir::homePath() + "app/native/assets/images/"
+ QString("multipleActive.png");
createAndSaveImage(m_savingFilePath, m_dataLoaded);
but when I try to use this image, I am getting the error below.
"Unable to get asset in (/apps/com.bluewave.LeasePlan.testDev_e_LeasePlan45b0f435/native/assets/): (/images/multipleActive.png)."
The assets directory (or more properly the app directory) is part of the protected area of the application sandbox that can not be changed. If you want to store data in the sandbox you should use the data directory.
See: https://developer.blackberry.com/native/documentation/cascades/device_platform/data_access/file_system.html
I'm using the following function to convert paths into a valid Virtual Path:
public string GetFullPath(string path)
{
Ensure.Argument.NotNullOrEmpty(path, "path");
if (path[0] == '~') // a virtual path e.g. ~/assets/style.less
{
return path;
}
if (VirtualPathUtility.IsAbsolute(path)) // an absolute path e.g. /assets/style.less
{
return VirtualPathUtility.ToAppRelative(path,
HostingEnvironment.IsHosted ? HostingEnvironment.ApplicationVirtualPath : "/");
}
// otherwise, assume relative e.g. style.less or ../../variables.less
return VirtualPathUtility.Combine(VirtualPathUtility.AppendTrailingSlash(currentFileDirectory), path);
}
This passes all my tests other than for when the input path is a relative path, above the website directory.
For example given a currentFileDirectory of ~/foo/bar and a relative path of ../../../ I want to detect this and attempt to fix the path.
Server.MapPath is an easy way to validate either virtual or dos style paths. Validation is restricted for security reasons from validating any physical paths that are outside the web site. See my comment above.
To elaborate on Mike's answer we can validate whether a relative path attempts to go outside of the physical web site directory by:
Getting the combined path of the current path and relative path using Path.GetFullPath
Getting the file system path of the attempted path using Server.MapPath
Getting the file system path of the root of the application
Validating that the attempted path exists within the root path
Example:
var currentFileDirectory = "~/foo/bar";
var relativePath = "../../../";
var attemptedPath = Path.GetFullPath(Path.Combine(Server.MapPath(currentFileDirectory), relativePath)); // 1 + 2
var rootPath = Server.MapPath("~/"); // 3
if (attemptedPath.IndexOf(rootPath, StringComparison.InvariantCultureIgnoreCase) == -1) // 4
{
throw new Exception(string.Format("Path {0} is outside path {1}",
rootPath, HostingEnvironment.ApplicationPhysicalPath));
}