2017-06-30 5 views
5

J'essaie d'ajouter des fonctionnalités hors ligne à mon lecteur vidéo HTML5. J'essaye d'écrire les dossiers dans le système de fichiers de chrome comme blob et puis les lis de là. Je crois que je cours dans un problème où les dossiers ne sont pas réellement écrits, juste le nom de dossier. Comme mon code ci-dessous est actuellement constitué, il fonctionne, mais toujours uniquement s'il est connecté en permanence à Internet. Mon objectif est de télécharger les fichiers dans un répertoire permanent du système de fichiers, puis de continuer à les lire si Internet est déconnecté.Utilisation du système de fichiers comme source de vidéos pour la lecture hors connexion

$(document).ready(function() { 


    var dir = "http://www.kevmoe.com/networks/gsplayer/"; 
    var fileextension = ".mp4"; 
    var srcfiles = $.ajax({ 
     //This will retrieve the contents of the folder if the folder is configured as 'browsable' 
     url: dir, 
     success: function(data) { 
      //List all .mp4 file names in the page 
      $(data).find("a:contains(" + fileextension + ")").each(function() { 
       var filename = $(this).attr("href").replace(window.location.host, "").replace("http://", ""); 

       $("#container").append("<div id='div1' class='video'><video id='video1' class='vidarray' preload='none' poster='bkg.png'><source src='" + filename + "' type='video/mp4'></video></div>"); 
       async: false; 


       window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 

       window.requestFileSystem(window.PERSISTANT, 200000 * 1024 * 1024, initFS, errorHandler); 

       function initFS(fs) { 
        console.log('filesystem engaged'); // Just to check if everything is OK :) 
        // place the functions you will learn bellow here 
        function errorHandler(err) { 
         var msg = 'An error occured: '; 
        }; 

        function createDir(rootDir, folders) { 
         rootDir.getDirectory(folders[0], { 
          create: true 
         }, function(dirEntry) { 
          if (folders.length) { 
           createDir(dirEntry, folders.slice(1)); 
          } 
         }, errorHandler); 
        }; 

        createDir(fs.root, 'files/video/'.split('/')); 

        fs.root.getDirectory('video', {}, function(dirEntry) { 
         var dirReader = dirEntry.createReader(); 
         dirReader.readEntries(function(entries) { 
          for (var i = 0; i < entries.length; i++) { 
           var entry = entries[i]; 
           if (entry.isDirectory) { 
            console.log('Directory: ' + entry.fullPath); 
           } else if (entry.isFile) { 
            console.log('File: ' + entry.fullPath); 
           } 
          } 

         }, errorHandler); 
        }, errorHandler); 

        fs.root.getFile(filename, { 
         create: true, 
         exclusive: true 
        }, function(fileEntry) { 
         fileEntry.createWriter(function(fileWriter) { 
          var blob = new Blob([data], { 
           type: 'video/mp4' 
          }); 
          fileWriter.write(blob); 
         }, errorHandler); 

         console.log('file downloaded'); 
        }, errorHandler); 

        //Try to add an event listener for when all files are finished loading into file system. Then use another function to source the videos locally. 
        var dirReader = fs.root.createReader(); 
        var entries = []; 

        // Call the reader.readEntries() until no more results are returned. 

        dirReader.readEntries(function(results) { 

         //List all .mp4 file names in the page 
         $(results).find("a:contains(" + fileextension + ")").each(function() { 
          var filename = $(this).attr("href").replace(window.location.host, "").replace("http://", ""); 

          $("#container").append("<div id='div1' class='video'><video id='video1' class='vidarray' preload='none' poster='bkg.png'><source src='" + filename + "' type='video/mp4'></video></div>"); 
          async: false; 

         }, errorHandler); 
        }); 
       }; 

       function errorHandler() { 
        console.log('An error occured'); 
       }; 
      }); 


      var videos = $('.video'); 
      //handle ending of video 
      videos.find('video').on('ended', function() { 
       playNextVideo(videos); 
      }); 

      // start with the first one 
      playNextVideo(videos); 


      function playNextVideo(videoList) { 
       var activeVideo = videoList.filter('.active').removeClass('active'), // identify active video and remove active class 
        activeIndex = videoList.index(activeVideo), // get the active video index in the group 
        nextVideo = videoList.eq(activeIndex + 1), // get the next video in line 
        actualVideo; 

       // if there is no next video start from first 
       if (nextVideo.length == 0) nextVideo = videoList.first(); 

       // pause all videos 
       videoList.find('video').each(function() { 
        this.pause(); 
       }) 

       // get reference to next video element 
       actualVideo = nextVideo.find('video').get(0); 

       // add active class to next video 
       nextVideo.addClass('active'); 

       // load and play 
       actualVideo.volume = 0.04; 
       actualVideo.load(); 
       actualVideo.play(); 
      } 
     } 
    }); 
}); 
+0

Would ayant le cache du navigateur la vidéo résoudre localement votre problème ou insistez-vous qu'il est téléchargé dans un répertoire particulier pour une utilisation hors ligne? Si vous en avez juste besoin pour pouvoir lire les vidéos hors ligne [cette question stackoverflow] (https://stackoverflow.com/questions/34668291/html-video-in-browser-cache) peut vous être utile. –

+1

Cela peut être juste une faute de frappe mais 'window.PERSISTANT' est indéfini alors que' window.PERSISTENT' est 1. Si ce n'est pas (une faute de frappe) alors vous écrivez probablement à TEMPORARY au lieu de stockage PERSISTENT. – IronGeek

+0

Christopher. J'ai essayé de mettre en cache mais cela ne fonctionnait pas pour les fichiers plus volumineux. – KevMoe

Répondre

1

filesystem: stocke les fichiers de protocole en référence à même origine que document qui demande LocalFileSystem. Autrement dit, si JavaScript est créé à, par exemple, http://example.org, le chemin d'accès à LocalFileSystem doit avoir la même origine que http://example.org, et non file:.

Si vous essayez de stocker des fichiers ou des dossiers pour l'accès au protocole file:, hors ligne, vous pouvez créer un document .html à utiliser comme modèle de signet.

Visitez le fichier local .html une fois en ligne pour obtenir des fichiers et remplir LocalFileSystem. Si navigator.onLine est true, accédez à http://example.org, sinon obtenez et traitez les fichiers et dossiers stockés au LocalFileSystem.

Créer une liste comme JSON ou JavaScript Array pour stocker la liste des fichiers pour aller chercher, au lieu d'analyser un .htmldocument pour l'emplacement des fichiers.

Enregistrez le fichier local en tant que signet. Lancer Chrome, Chrome avec --allow-file-access-from-files drapeau défini pour accéder au protocole filesystem: du protocole file: et le protocole file: au protocole filesystem:, sinon en ligne.

<!DOCTYPE html> 
<html> 
<head> 
    <title>LocalFileSystem Offline Videos Bookmark</title> 
</head> 
<body> 
<script> 

// location to visit if online 
const onLineURL = "https://lorempixel.com/" 
        + window.innerWidth 
        + "/" 
        + window.innerHeight + "/cats"; 

const props = { 
    requestedBytes: 1024 * 1024 * 20000, 
    folder: "videos", 
    // list of files to fetch for offline viewing 
    mediaList: [ 
    "http://mirrors.creativecommons.org/movingimages/webm/" 
    + "ScienceCommonsJesseDylan_240p.webm" 
    , "https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4" 
    ] 
}; 

let grantedBytes = 0; 

function getLocalFileSystem ({requestedBytes = 0, mediaList=[], folder = ""}) { 
    if (!requestedBytes || !mediaList.length || !folder) { 
     throw new Error("requestedBytes: Number" 
        + " or mediaList: Array" 
        + " or folder: String not defined"); 
    }; 
    // do stuff with `filesystem:` URL 
    function processLocalFilePath(localPath) { 
     const video = document.createElement("video"); 
     document.body.appendChild(video); 
     video.controls = true; 
     video.src = localPath; 
    } 

    function errorHandler(err) { 
     console.log(err); 
    } 

    function writeFile(dir, fn, fp, localPath) { 
     console.log(dir, fn, fp, localPath); 
     dir.getFile(fn, {}, function(fileEntry) { 
      fileEntry.createWriter(function(fileWriter) { 
       fileWriter.onwriteend = function(e) { 
        // do stuff when file is written 
        console.log(e.type, localPath + " written"); 
        window.webkitResolveLocalFileSystemURL(localPath 
        , function(file) { 
         // file exists in LocalFileSystem 
         processLocalFilePath(localPath); 
        }, errorHandler) 
       }; 

       fileWriter.onerror = errorHandler; 
       fetch(fp).then(function(response) { 
        return response.blob() 
       }).then(function(blob) { 
        fileWriter.write(blob); 
       }).catch(errorHandler) 
      }, errorHandler); 
     }, errorHandler); 
    } 

    if (mediaList && mediaList.length) { 
     navigator.webkitTemporaryStorage.requestQuota(requestedBytes 
     , function(grantedBytes_) { 
      grantedBytes = grantedBytes_; 
      console.log("Requested bytes:", requestedBytes 
         , "Granted bytes:", grantedBytes); 
      window.webkitRequestFileSystem(window.TEMPORARY 
      , grantedBytes 
      , function(fs) { 

       const url = fs.root.toURL(); 

       mediaList.forEach(function(filename) { 

        const localPath = url + folder + "/" 
             + filename.split("/").pop(); 

        window.webkitResolveLocalFileSystemURL(localPath 
        , function(file) { 
         // file exists in LocalFileSystem 
         console.log(localPath + " exists at LocalFileSystem"); 
         processLocalFilePath(localPath) 

        }, function(err) { 
         console.log(err, localPath 
         + " not found in LocalFileSystem"); 
         // Exception is thrown if file 
         // or folder path not found 
         // create `folder` directory, get files 
         fs.root.getDirectory(folder, {} 
         , function(dir) { 
          writeFile(dir 
          , filename.split("/").pop() 
          , filename 
          , localPath); 
         }), 
         errorHandler 
        }) 
       }) 

      }) 
     }, errorHandler) 
    } 
} 

if (location.href !== onLineURL && navigator.onLine) { 
    location.href = onLineURL; 
} else { 
    getLocalFileSystem(props); 
} 

</script> 
</body> 
</html> 

Voir aussi


Une autre approche pourrait être d'utiliser ServiceWorker

1

Votre nom d'utilisateur doit accorder votre autorisation d'application pour stocker des données localement avant que votre application peut utiliser le stockage persistant. C'est pourquoi vous devez d'abord demander un quota. La quantité d'octets que vous demandez est de 200000 * 1024 * 1024 octets.

window.storageInfo.requestQuota(PERSISTENT, 200000 * 1024 * 1024, 
    function(grantedBytes) { 
     window.requestFileSystem(window.PERSISTENT, grantedBytes, onInitFs, errorHandler); 
    }, 
    errorHandler 
); 

MDN documentation

Je remarque que vous écrivez ceci pour Chrome, here's how you manage the quota in Chrome