2015-12-18 11 views
7

Ho un file PDF che viene scaricato su tutti i browser ad eccezione di Firefox/Safari. Lo apre nella finestra del browser invece del download del file. Il mio sito è in esecuzione su node.js e è ospitato in Azure. Il download degli utenti del file proviene dallo storage BLOB di Azure, quindi sospetto che possa trattarsi di un problema CORS.AngularJS forza Firefox/Safari per scaricare il file anziché aprire nel browser

Ecco il mio codice lato client per il download:

<a href="{{fileURL}}" class="btn btn-default" download="myfile.pdf">Download File</a> 

ecco il codice lato server:

$scope.fileURL = 'https://myblob.blob.core.windows.net/8282020/myfile.pdf'; 

Aggiornamento: Sono in grado di aggiungere la disposizione dei contenuti impostando il proprietà BLOB in Azure per la guida in basso, e sta visualizzando la disposizione come "allegato" ma in FireFox/Safari è ancora aperta nel browser. È possibile che questo sia bloccato poiché lo spazio di archiviazione BLOB di Azure potrebbe essere visualizzato come CORS?

Aggiornamento 2: L'aggiunta dei seguenti alla mia tag HTML sembra funzionare in Firefox (ma non Safari), che cosa è questo il modo giusto per gestire questa situazione tutti i browser

type="application/octet-stream" 

Update 3: Sembra che la disposizione del contenuto e il tipo di contenuto tramite Node funzionino. Devo chiedere, è questa la strada giusta?

blobSvc.setBlobProperties(containerName, filename, { contentDisposition: 'attachment', contentType: 'application/octet-stream' }, function (error, result, response) { 
// result code here.... 
}) 
+0

Questo potrebbe essere utile http://stackoverflow.com/questions/11353425/force-a-browser-to-save-file-as-after-clicking-link –

+0

Ho già il tag di download, funziona in alcuni browser ma non Safari e Firefox – Kode

+0

È possibile aggiungere un'intestazione "Content-disposition: attachment" alla risposta che serve al file? – theadriangreen

risposta

1

È possibile aggiungere un'intestazione "Content-disposition: attachment" alla risposta che serve il file. Poiché il tuo file è archiviato nell'archivio BLOB di Azure, dovrai eseguire il proxy della richiesta tramite l'app del nodo.

Così il codice originale sarebbe cambiato a qualcosa di simile:

$scope.fileURL = '<your-node-app-address>/myfile.pdf'; 

e

<a href="{{fileURL}}" class="btn btn-default" download="myfile.pdf">Download File</a> 

Poi si sarebbe impostare un percorso nel nodo applicazione a <your-node-app-address>/myfile.pdf e basta collegare l'intestazione corretta, con qualcosa del tipo:

var client = restify.createStringClient({ 
     url: 'https://myblob.blob.core.windows.net' 
    });  
client.get('/8282020/myfile.pdf', function(err, req, res, data) { 
      response.setHeader('Content-Disposition', 'attachment'); 
      response.writeHead(res.statusCode); 
      response.write(data); 
      response.end(); 
     }); 
+0

È possibile ripristinare un modulo nodo o integrato? – Kode

+1

Sì, è un modulo di nodo integrato, ma è solo un codice di esempio. In sostanza, devi solo fare un'altra richiesta al tuo blob e allegare l'intestazione, che è ciò che stavo cercando di trasmettere. – theadriangreen

+0

Come trovo l'indirizzo dell'app per il mio nodo? (Probabilmente qualcosa di base mi manca) – Kode

1

Ci sono due modi per farlo con lo streaming dei contenuti tramite il server Web ed entrambi implicano l'impostazione della proprietà Content-Disposition sul BLOB stesso.

  1. sempre scaricare: Se si desidera che il file da scaricare sempre, quello che si potrebbe fare è impostare la proprietà Content-Disposition sul blob stesso. In questo modo ogni volta che qualcuno accede al blob, il file verrà sempre scaricato.
  2. Scarica A volte: Se si desidera che il file da scaricare a volte mentre aprire il browser a volte, che cosa si può fare è creare un Shared Access Signature (SAS) sul blob con almeno Read permessi e sovrascrivere Content-Disposition intestazione di risposta nel SAS quando vuoi per scaricare il file. Se si desidera aprire il file nel browser, omettere semplicemente questa intestazione di risposta nel SAS.

Leggere il numero Overriding Commonly Used Headers in SAS nel mio blog: http://gauravmantri.com/2013/11/28/new-changes-to-windows-azure-storage-a-perfect-thanksgiving-gift/.

UPDATE

ma come faccio a impostare il Content-Disposition in Azure Blob Storage? è qualcosa che posso impostare su tutti i miei contenitori BLOB usando qualcosa di come Azure Storage Explorer? O devo impostarlo per blob/come farebbe ?

Questo è qualcosa che dovresti fare per ogni blob nel tuo contenitore. Non puoi farlo a livello di contenitore. Non credo che Azure Storage Explorer supporti questa funzionalità. Nello strumento che sto creando (Cloud Portam - http://www.cloudportam.com), ho incluso questa funzionalità, ma dovresti farlo di nuovo per ogni singolo BLOB. Un'altra alternativa è aggiornare le proprietà del BLOB utilizzando qualsiasi SDK client. L'approccio sarebbe quello di elencare i BLOB in un contenitore (che dovrebbe fornire le proprietà BLOB), aggiornare la proprietà ContentDisposition e salvare le proprietà.

UPDATE 2

Posso impostare la disposizione sul caricamento iniziale? Sto usando Nodo/JavaScript: blobSvc.createBlockBlobFromLocalFile ('mycontainer', 'myblob', 'test.txt', funzione (errore, risultato, risposta) {if (! Errore) { // file caricato}}) ;

Certo che puoi! Dai un'occhiata al codice sorgente per createBlockBlobFromLocalFile qui: https://github.com/Azure/azure-storage-node/blob/master/lib/services/blob/blobservice.js. È possibile impostare la proprietà content-diposition fornendo il valore appropriato in options.contentDisposition.

+0

# 1 potrebbe essere quello che sto cercando. Ho letto il tuo blog (ottimo in ogni caso), ma come faccio a impostare la disposizione del contenuto in Archiviazione BLOB di Azure? È qualcosa che posso impostare su tutti i miei contenitori BLOB usando qualcosa come Azure Storage Explorer? O ho bisogno di impostarlo per blob/come farei questo? – Kode

+0

Aggiornato la mia risposta con la risposta ai vostri commenti. HTH. –

+0

Posso impostare la disposizione sul caricamento iniziale? Sto usando Node/JavaScript: blobSvc.createBlockBlobFromLocalFile ('mycontainer', 'myblob', 'test.txt', funzione (errore, risultato, risposta) {if (! Errore) {// file caricato}}); – Kode

2

In generale, possiamo impostare la Content-Disposition di blob per attachment per indicare che l'user-agent non deve visualizzare la risposta, ma invece mostrare una finestra di dialogo Salva con un nome diverso dal nome blob specificato. Per ulteriori informazioni, fare riferimento a Set Blob Properties.

Posso impostare la disposizione sul caricamento iniziale? Sto usando Node/JavaScript: blobSvc.createBlockBlobFromLocalFile ('mycontainer', 'myblob', 'test.txt', funzione (errore, risultato, risposta) {if (! Errore) {// file caricato}});

Nella mia prova, devo setBlobProperties dopo ha creato il blob in Azure, ho impostato il successo sarà il Content-Disposition del blob.

E.G.

blobsrv.createBlockBlobFromLocalFile('mycontainer', 'Azure.pdf', 'upload/Azure.pdf', function (error, result, response) { 

     if (error) res.send(500); 
     blobsrv.setBlobProperties('mycontainer', 'Azure.pdf', { contentDisposition: 'attachment' }, function (error, result, response) { 
      res.send(200, JSON.stringify(response)); 
     }) 
    }); 

E il frontend angolare scaricherà il file anziché aprirlo direttamente nel browser FireFox nel mio test.

<a href="{{pdfurl}}" download="Azure.pdf">Azure.pdf</a> 
$scope.pdfurl = "http://<cantainer>.blob.core.windows.net/mycontainer/Azure.pdf"; 
+0

Strano, sta mostrando la disposizione del contenuto come allegato, ma in Firefox si sta ancora aprendo nel browser invece del download. – Kode

0

L'impostazione della disposizione del contenuto e del tipo di contenuto tramite Node sembra funzionare. Sembra che entrambi siano necessari.

blobSvc.setBlobProperties(containerName, filename, { contentDisposition: 'attachment', contentType: 'application/octet-stream' }, function (error, result, response) { 
// result code here.... 
}) 
Problemi correlati