as3 file download restrain? - actionscript-3

I have a flash download on my site to download a pdf file.
var myfileReference:FileReference = new FileReference();
down_mc.visible = false;
down_comp.visible = false;
var myRequest:URLRequest = new URLRequest("GEORGIA INCORPORATED.pdf");
myfileReference.addEventListener(IOErrorEvent.IO_ERROR, ioError);
output_txt.text = "";
function ioError(event:ErrorEvent):void {
output_txt.text = "Sorry that there is an IO error during the file downloading. The error is:" + "\n" + event;
}
myfileReference.addEventListener(ProgressEvent.PROGRESS, fileDownloadProgress);
function fileDownloadProgress(event:ProgressEvent):void {
down_mc.visible = true;
}
myfileReference.addEventListener(Event.COMPLETE, fileDownloadCompleted);
function fileDownloadCompleted(evt:Event):void {
down_mc.visible = false;
down_comp.visible = true;
}
function downloadFile (event:MouseEvent):void {
try {
myfileReference.download(myRequest);
} catch (error:SecurityError) {
downloading. The error is:" + "\n" + error;
} catch (error:IllegalOperationError) {
downloading. The error is:" + "\n" + error;
}
}
b1.addEventListener(MouseEvent.CLICK, downloadFile);
the problem is some people want to change the name of the file they are downloading and changing the extension as well, the .pdf , thus making the file unusable. is there any way to restrain the clients from changing the extension?

In pure as3, you cannot force user to save a file under a specific extention. The only way to do it should be to use Air that let you have control on it through a FileStream Object (you can choose file name).
If you want to do it with Air, then you can do :
// Assuming you get your pdf raw data
var pdfData : ByteArray;
var f : File = File.desktopDirectory.resolvePath("myPdf.pdf");
// When user have select a file
f.addEventListener(Event.SELECT, function(e:Event):void{
var targetFile : File = e.target as File;
// Check if the selected file have pdf extension
if(targetFile.nativePath.substr(targetFile.nativePath.length - 4) != ".pdf")
// If not, add it
targetFile = new File(targetFile.nativePath + ".pdf");
// Save the file
var fs : FileStream = new FileStream();
fs.open(targetFile, FileMode.WRITE);
fs.writeBytes(pdfData);
fs.close();
});
// Ask user to save a file (by default on user desktop)
f.browseForSave("Save PDF");

Related

Move files from applicationStorage to Documents in app

I've got an app that, since 5 years now, that displays an offline map by reading from a folder embed in it ("assets").
Since Android 11, it's impossible to read from ApplicationStorage (Error #3001: File or directory access denied), so I'm trying to copy the folder from applicationStorage to "Documents".
What I did :
source = File.applicationDirectory.resolvePath("assets/maps");
destination = File.documentsDirectory.resolvePath("Documents/www");
source.addEventListener(Event.COMPLETE, onMapCopyComplete);
source.copyToAsync(destination, false);
function onMapCopyComplete(e: Event): void {
source.removeEventListener(Event.COMPLETE, onMapCopyComplete);
log("onMapCopyComplete()");
}
I've got a return onMapCopyComplete() but when I'm looking in InternalStorage/Documents of my phone I've got the folders but all are empty... None of the files were copy..
PrintScreen computer vs phone
To read the files, here's what I'm doing :
function startMapsView()
{
var indexFile:File = File.applicationStorageDirectory.resolvePath("www/index.html");
if (!indexFile.exists)
{
log("startMapsView() Index file not found, Please check www/index.html");
return;
}
// Create StageWebView
stageWebView = new StageWebView(isMobile); // Set to TRUE for System's NativeWebView, FALSE is for AIR's WebView
stageWebView.stage = stage;
stageWebView.viewPort = new Rectangle(0, iOSStatusBarHeight + headerBarHeight, deviceStageSize.width, deviceStageSize.height - (iOSStatusBarHeight + headerBarHeight + footerBarHeight));
stageWebView.addEventListener(flash.events.Event.COMPLETE, onStageWebViewLoaded);
stageWebView.addEventListener(flash.events.ErrorEvent.ERROR, onStageWebViewError);
stageWebView.addEventListener(LocationChangeEvent.LOCATION_CHANGING, onStageWebViewLocationChanging);
// Load Map URL
stageWebView.loadURL(mapsURL);
}
And mapsURL is define by :
function setMapsURL(doNotEnableButtons: Boolean = false): void {
var indexFile: File = File.documentsDirectory.resolvePath("Documents/www/index.html");
trace("indexFile url is = "+indexFile.url);
if (!indexFile.exists) {
log("setMapsURL() Index file not found, Please check www/index.html");
return;
}
var assetsDir: File;
if (!useOnlineMaps) {
assetsDir = new File(destination.resolvePath("index.html").nativePath);
} else {
assetsDir = new File(destination.resolvePath("onlineMaps.html").nativePath);
mySavedData.data.onlineMapChoosen = false;
}
mapsURL = assetsDir.url;
log("setMapsURL() " + mapsURL);
if (!doNotEnableButtons) enableMapButtons();
}

Gdrive unable to download and not upload

I am using GDRive insertFile and RevtrieveAllFiles to upload and download files to googledrive.
I created a client secret and Id and modified the credentials.
the code is based on the post in code project http://www.codeproject.com/KB/WPF/488185/GDrive_Uploader_Sample.zip
but it fails debuggin the Utilities.InsertFile
in the file.upload it fails with exceptionvalue cannot be null - uriString .
in the download it fails in FileList files = request.Fetch(); with
// First, create a reference to the service you wish to use.
// For this app, it will be the Drive service. But it could be Tasks, Calendar, etc.
// The CreateAuthenticator method is passed to the service which will use that when it is time to authenticate
// the calls going to the service.
_service = new DriveService(CreateAuthenticator());
// Open a dialog box for the user to pick a file.
OpenFileDialog dialog = new OpenFileDialog();
dialog.AddExtension = true;
dialog.DefaultExt = ".txt";
dialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
dialog.Multiselect = false;
dialog.ShowDialog();
File body = new File();
body.Title = System.IO.Path.GetFileName(dialog.FileName);
body.Description = "A test document";
body.MimeType = "text/plain";
System.IO.Stream fileStream = dialog.OpenFile();
byte[] byteArray = new byte[fileStream.Length];
fileStream.Read(byteArray, 0, (int)fileStream.Length);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
// Get a listing of the existing files...
List<File> fileList = Utilities.RetrieveAllFiles(_service);
// Set a flag to keep track of whether the file already exists in the drive
bool fileExists = false;
foreach (File item in fileList)
{
if (item.Title == body.Title)
{
// File exists in the drive already!
fileExists = true;
MessageBoxResult result = System.Windows.MessageBox.Show("The file you picked already exists in your Google Drive. Do you wish to overwrite it?", "Confirmation", MessageBoxButton.YesNoCancel);
if (result == MessageBoxResult.Yes)
{
// Yes... overwrite the file
Utilities.UpdateFile(_service, item.Id, item.Title, item.Description, item.MimeType, dialog.FileName, true);
List<File> allFiles = Utilities.RetrieveAllFiles(_service);
}
else if (result == MessageBoxResult.No)
{
// MessageBoxResult.No code here
File f= Utilities.insertFile(_service, System.IO.Path.GetFileName(dialog.FileName), "An uploaded document", "", "text/plain", dialog.FileName);
}
else
{
// MessageBoxResult.Cancel code here
return;
}
break;
}
}
// Check to see if the file existed. If not, it is a new file and must be uploaded.
if (!fileExists)
{
File file= Utilities.insertFile(_service, System.IO.Path.GetFileName(dialog.FileName), "An uploaded document", "", "text/plain", dialog.FileName);
var list = Utilities.RetrieveAllFiles(_service);
}
System.Windows.MessageBox.Show("Upload Complete");
open gdrive and set sdk to On. that will enable the application to access the gdrive account

FileReference.save ensuring it has extension

I need to save an XML with some settings and wanted to save them as my own filetype (.genconf for example). When i use..
var f:FileReference = new FileReference();
f.save( MyByteArray);
..I can allow the user to browse to save, but it only uses an extension if they enter in manually (which they definitely wont).
Is there a way to check the filename they enter, and amend/append it before the file is written?
Here's how i did it in the end (with AIR):
//on save clicked
public function export(e:MouseEvent){
var file:File = File.desktopDirectory;
file.browseForSave("Save");
file.addEventListener(Event.SELECT, onSaveSelect);
}
public function onSaveSelect(e:Event){
//create XML stuff here
var config:XML = new XML(<config />)
// compressing before saving
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes( config );
bytes.compress();
//get browse location
var saveFile:File = File(e.target);
var directory:String = saveFile.url;
//check if by miracle they put the extension in, then add it
if(directory.indexOf(".genconf ") == -1){
directory += ".genconf ";
}
//use the new path with the extension
var file:File = new File();
file = file.resolvePath(directory);
var fileStream:FileStream = new FileStream();
fileStream.addEventListener(Event.CLOSE, onClose);
fileStream.openAsync(file, FileMode.WRITE);
fileStream.writeBytes(bytes);
fileStream.close();
}
I think that for Flash security reason you can not force the file extension in any way, in addition the file name typed by user is a read-only information so you can not modify it.
So for your case, you want to save files with the .genconf extension, I think that you can :
Request the file name to your user, before showing the save dialog, and then add the extension to have the default file name for the save dialog.
OR
Fix the default file name with your extension using time-stamp, randomized name, ... and demand to your user to save the file directly without editing the name.
In all cases, you will get a code like this :
const extension:String = '.genconf';
var file_ref:FileReference = new FileReference()
file_ref.save('your_data', 'default_file_name' + extension);
Hope that can help.

Changing the name of a file with FileWriter

I wonder if it is possible to rename a file with FileWriter function. At this point, I can save my file without problem. But I'd like to change her name when saving. Here is my function:
function saveFile() {
var s = fileEntry.name;
var new_name = s.substring(0, s.lastIndexOf(".")) + ".min" + s.substring(s.lastIndexOf("."))
fileEntry.name = new_name;
fileEntry.createWriter(function(fileWriter) {
fileWriter.onerror = function(e) {
console.log("Write failed: " + e.toString());
};
var blob = new Blob([textarea.value]);
fileWriter.truncate(blob.size);
fileWriter.onwriteend = function() {
fileWriter.onwriteend = function(e) {
console.log("Write completed.");
};
// fileWriter.write(blob);
}
}, errorHandler);
}
I guess it's possible, but I can not find how.
Thank you in advance!
To do this you need to use the DirectoryEntry API. To write to a new file you will need to use getFile to create a new file and write the contents into it.
To do this you also need to have access to the directory where you want to create the new file, and also permissions to create a file there. If the directory is within your sandboxed file system, this isn't a problem.
If you want to create the file on the user's file system it is more complicated. The user will need to have given your app access to the folder (via chrome.fileSystem.chooseEntry) and your app will need to have the chrome.fileSystem.directory and chrome.fileSystem.write permissions.

File class AS3 / AIR: let user choose only save location, not file name or extension

When using browseForSave method, is it possible to let the user choose only the location of a file, and not the file name or the extension?
I'm creating an encrypted file, and I need its name and extensions not to be changed by the user.
Thx!
EDIT (AFTER SOLVED)
I was simply looking for the browseForDirectory method. Shame on me. :)
For a reference on how to open a browse dialog to choose a folder see the example here:
How to create "Browse for folder" dialog in Adobe FLEX?
once you have your directory you can piece that together with code here to save a file using the FileStream object:
http://blog.everythingflex.com/2008/02/25/file-and-filestream-within-air/
copied here since it's an external link
private function saveFile():void{
var myPattern:RegExp = / /g;
var newFileName:String = fileName.text.replace('.txt','');
if(newFileName.length > 1){
var file:File = File.desktopDirectory.resolvePath("Files/" + newFileName.replace(myPattern,'_') + ".txt");
var stream:FileStream = new FileStream()
stream.open(file, FileMode.WRITE);
var str:String = contents.text;
str = str.replace(/\r/g, File.lineEnding);
stream.writeUTFBytes(str);
stream.close();
fdg.directory = File.desktopDirectory.resolvePath("Files/");
fileName.text = "";
contents.text = "";
} else {
mx.controls.Alert.show("File name is required", "Error Saving File");
}
}
One solution would be to set the file object like this:
var f:File = File.desktopDirectory.resolvePath("*.txt");
f.addEventListener(Event.SELECT, onSelected);
f.browseForSave("save txt file");
Although user can still override that in the opened dialog, but at least the dialog shows the file extension. And later in the Event.SELECT you can check and confirm what user has selected.