Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save file using binary string on Android via HTML5

I'm working with a small three-man team with my app and we're stuck.

We're using JSZip and FileSaver to save files for our code editor application. It works fine in the browser, but when I use it with PhoneGap as a native Android application it doesn't write.

This problem still occurs with the zip.js library and even saving single files with the FileSaver.js library.

$('.savemd').click ->
  blob = new Blob([ mdEditor.getValue() ], type: 'text/x-markdown')
  saveAs blob, 'source.md'

I tried using PhoneGap's FileWriter object, but later I found that it's currently impossible to write binary data with Phonegap's FileWriter - source - source

However that post is a few years old.

I've also tried getting this to work with native WebView and using the Crosswalk Project and still no luck.

We've also tried...

function saveFile(fileName, fileData) {
  // Get access to the file system
  window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) {
    // Create the file.
    fileSystem.root.getFile(fileName, { create: true, exclusive: false }, function (entry) {
      // After you save the file, you can access it with this URL
      myFileUrl = entry.toURL()
      entry.createWriter(function(writer) {
        writer.onwriteend = function(evt) {
          alert("Successfully saved file to " + myFileUrl)
        }
        // Write to the file
        writer.write(fileData)
      }, function(error) {
        alert("Error: Could not create file writer, " + error.code)
      })
    }, function(error) {
      alert("Error: Could not create file, " + error.code)
    })
  }, function(evt) {
    alert("Error: Could not access file system, " + evt.target.error.code)
  })
}

The problem with this is it only saves to the users memory (sd card in or not, we've tested on all our android devices and still doesn't work, but note that we are not using any rooted devices), and will not work with JSZip.

Our team develops on many different operating systems (Mac, Android, Chromebook's) so PhoneGap Build is currently a requirement.

Does anyone know of any way to do this? This being referred to Saving a file using a Binary String on Android via HTML5? (PhoneGap or PhoneGap builds answer is preferred).

Here's our current XML for PhoneGap Build:

<?xml version="1.0" encoding="utf-8"?>
<widget xmlns = "http://www.w3.org/ns/widgets"
  xmlns:gap   = "http://phonegap.com/ns/1.0"
  id          = "com.save.test"
  version     = "1.0.0"
  versionCode = "1">
  <name>SaveTest</name>
  <description>
      Save file using a Binary string test on Android
  </description>
  <author email="[email protected]" href="http://mikethedj4.github.io/">
      Michael Schwartz
  </author>

  <content src="index.html" />

  <icon src="icon.png" gap:role="default" />
  <icon gap:platform="android" gap:qualifier="ldpi" src="res/icon/android/icon-36-ldpi.png" />
  <icon gap:platform="android" gap:qualifier="mdpi" src="res/icon/android/icon-48-mdpi.png" />
  <icon gap:platform="android" gap:qualifier="hdpi" src="res/icon/android/icon-72-hdpi.png" />
  <icon gap:platform="android" gap:qualifier="xhdpi" src="res/icon/android/icon-96-xhdpi.png" />
  <icon gap:platform="android" src="res/icon/android/icon-96-xhdpi.png" />
  <icon gap:platform="ios" height="57" src="res/icon/ios/icon-57.png" width="57" />
  <icon gap:platform="ios" height="72" src="res/icon/ios/icon-72.png" width="72" />
  <icon gap:platform="ios" height="114" src="res/icon/ios/icon-57-2x.png" width="114" />
  <icon gap:platform="ios" height="144" src="res/icon/ios/icon-72-2x.png" width="144" />
  <icon gap:platform="winphone" src="res/icon/windows-phone/icon-48.png" />
  <icon gap:platform="winphone" gap:role="background" src="res/icon/windows-phone/icon-173-tile.png" />

  <preference name="permissions" value="none"/>
  <!-- <plugin name="org.crosswalk.engine" spec="1.3.0" source="pgb" /> -->
  <!-- <plugin name="cordova-plugin-crosswalk-webview" source="npm" /> -->
  <plugin name="cordova-plugin-whitelist" source="npm" />
  <plugin name="cordova-plugin-device" source="npm" />
  <plugin name="cordova-plugin-file" source="npm" />
  <plugin name="cordova-plugin-file-transfer" source="npm" />
  <plugin name="cordova-plugin-chrome-apps-filesystem" source="npm" />
  <!-- <plugin name="cordova-connectivity-monitor" source="npm" /> -->
  <preference name="phonegap-version" value="cli-5.2.0" />

  <allow-intent href="http://*/*" />
  <allow-intent href="https://*/*" />
</widget>

$('.download').click(function () {
  eval($('#jszipdemo').val())
})
.fill {
  width: 100%;
  display: block;
}
<link rel='stylesheet prefetch' href='http://treehouse-code-samples.s3.amazonaws.com/poly/css/application.css'>

<div class='grid'>
  <div class='grid__col--12'>
    <p></p>
    <button class='btn--default download fill'>Run</button>
    <textarea class='form__input' id='jszipdemo' placeholder='Demo code here...' rows='7'>var zip = new JSZip();&#x000A;zip.file("Hello.txt", "Hello World");&#x000A;var folder = zip.folder("images");&#x000A;folder.file("folder.txt", "I'm a file in a new folder");&#x000A;var content = zip.generate({type:"blob"});&#x000A;// see FileSaver.js&#x000A;saveAs(content, "example.zip");</textarea>
  </div>
</div>

<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script>
<script src='https://stuk.github.io/jszip/dist/jszip.js'></script>
<script src='https://stuk.github.io/jszip-utils/dist/jszip-utils.js'></script>
<script src='https://stuk.github.io/jszip/vendor/FileSaver.js'></script>
like image 241
Michael Schwartz Avatar asked Feb 24 '16 06:02

Michael Schwartz


1 Answers

You can save binary data with FileWriter, it was not possible in the past, but now it is.

Create your blob in this way :

var byteArray = new Uint8Array(fileContent.length);
for (var x = 0; x < byteArray.length; x++) {
    byteArray[x] = fileContent.charCodeAt(x) & 0xff
}

var blob = new Blob([byteArray], {
    type: 'application/octet-stream'
});

And then save it

fileWriter.write(blob);
like image 80
atrebbi Avatar answered Nov 16 '22 08:11

atrebbi