2017-07-26 59 views
7

Chciałbym ustawić nazwę pliku i format "pliku nietypowego", z powodu braku lepszych słów. Pliki są zapisywane w lokalizacjach takich jak poniżej ...Ustaw nazwę pliku i format, jeśli lokalizacja pliku lub pliku nie zawiera ani

let link = https://.../videoplayback?ipbits=0&initcwndb...D134213BA9465CB74DFD36CDE47BF.102638C4A9F3ACA357F79EE747DD5F49F1E0F0DE

Gdy ktoś pobiera takie pliki, nawet jeśli są one całkowicie różne pliki, zawsze w końcu jest zapisywane z tą samą nazwą i nigdy plik rozbudowa.

Próbowałem już url.download = link + '.mp4', ale nie ma to żadnego wpływu.

Jak mogę to zrobić?

+0

W jaki sposób pozyskujesz pliki? – TheChetan

+0

@ TheChetan pobieranie ich z Internetu za pośrednictwem przeglądarki – Anthony

+0

@Anthony Czy pliki są obsługiwane z nagłówkami 'CORS'? – guest271314

Odpowiedz

6

Według MDN dla anchor tags z pobierania atrybut:

może być używany z blob: adresów URL i danych: adresy URL, aby ułatwić użytkownikom do pobrania zawartości, która jest generowana programowo przy użyciu JavaScript (np. Zdjęcie utworzone za pomocą aplikacji internetowej do rysowania online).

Jeśli nagłówek HTTP Content-Disposition: występuje i podaje inną nazwę pliku niż , to nagłówek HTTP ma nad tym atrybutem priorytet .

Jeśli ten atrybut jest obecny i Content-Disposition: jest ustawiony na w linii, Firefox daje pierwszeństwo Content-Disposition, podobnie jak w przypadku nazwy pliku , natomiast Chrome daje pierwszeństwo atrybutowi pobierania.

Ten atrybut jest honorowana tylko linki do zasobów z tego samego pochodzenia .

Więc jeśli dynamicznie generujesz te linki i pochodzą one z Twojego własnego serwera - możesz ustawić nazwę pliku. Żądanie dotyczące pochodzenia krzyżowego nie zadziała!

Możliwe, że będziesz w stanie użyć pliku ajax, aby pobrać plik jako obiekt typu blob, i nakłonić przeglądarkę do myślenia, że ​​dane nie mają wielu źródeł. Zobacz this answer dla jednej możliwej implementacji.

+0

jakiś przykładowy kod? – Anthony

+0

Przy próbie tego na localhost/jsfiddle - pobieranie samego attr nie działa. Myślę, że ma to coś wspólnego z localhostem, który nie działa jako serwer. Mogłabym pracować nad Apache, ale nie chciałem tego robić, gdybyś zrobił to lokalnie. To obejście naprawiło jednak: https://gist.github.com/nelsonkhan/7d4e4b5c2f6898cf6a40bc12a236cbbb – Kwestion

+0

Powyższe działanie najprawdopodobniej zadziała w nowszych przeglądarkach, ale obsługa IE jest znanym problemem. Nie jestem pewien w przeglądarkach mobilnych - nie mogę znaleźć informacji o zgodności w dowolnym miejscu ... – Kwestion

3

Jedno podejście byłoby wykonać żądania HEAD przed ustawieniem .download własnością <a> elementu określić Content-Type żądanego zasobu, należy użyć JSON ciąg, obiekt JavaScript lub innego klawisza, format przechowywania danych para wartości, aby odzwierciedlić par ważny MIME typy dla prawidłowych rozszerzeń plików odpowiadających właściwości typu MIME. Użyj metody: .indexOf(), lub innej metody filtrowania w celu ustalenia, czy istnieje zgodność między nazwą właściwości ciągu lub obiektu a wartością właściwości, jeśli true, zapisz wartość rozszerzenia i połącz rozszerzenie z sugerowaną nazwą pliku.

Jeśli plik nie jest podawany z nagłówkami Cors można spróbować przy użyciu serwera proxy, aby HEAD z GET prośba, aby uzyskać nagłówek Content-Type przed ustawienie atrybutu .download.

Należy zauważyć, że atrybut .download jest tylko sugestią użytkownika dla nazwy pliku. Użytkownik może zmienić nazwę pliku w dowolnym czasie, w tym usunąć rozszerzenie pliku, z dowolnego powodu, który może mieć lub nie. Lub nie pobieraj zasobu w ogóle.

const mimeTypeExtensions = { 
 
    "text/plain": ".txt", 
 
    "video/mp4": ".mp4", 
 
    /* valid MIME types and corresponding extensions */ 
 
} 
 

 
const a = document.querySelector("a"); 
 

 
a.addEventListener("click", event => { 
 

 
    if (!a.download) { 
 
    
 
    event.preventDefault(); 
 
    
 
    fetch(a.href, {method: "HEAD"}) 
 
    .then(response => { 
 
     const mimeType = response.headers.get("content-type"); 
 
     let fileExtension = ""; 
 
     for (let [key, prop] of Object.entries(mimeTypeExtensions)) { 
 
      if (key.indexOf(mimeType) > -1) { 
 
      fileExtension = prop; 
 
      break; 
 
      }; 
 
     } 
 
     a.download = `filename${fileExtension}`; 
 
     a.click(); 
 
    }) 
 
    .catch(err => console.error(err)) 
 

 
    } 
 

 
});
<a href="https://gist.githubusercontent.com/guest271314/11edc4566ba94f204dd46e6ae26edaad/raw/d118e99abbe2a2c60634e46816df9e1b9de6b6b8/D134213BA9465CB74DFD36CDE47BF102638C4A9F3ACA357F79EE747DD5F49F1E0F0DE">click</a>

+0

Będę musiał ponownie przeczytać to, kiedy znajdę trochę czasu. czy możesz rozwinąć temat "... używając proxy do zrobienia' HEAD' z żądania 'GET' ...". Myślę, że rozumiem to, co mówisz, ale trudno to zrozumieć. – Anthony

2

Tutaj jest łatwym rozwiązaniem, jeśli nie przeszkadza dodając bibliotekę. FileSaver.js radzi sobie dobrze z tymi przypadkami podczas ukrywania brzydkich szczegółów. Zamierzałem przejść do sposobu, w jaki można utworzyć Blob, zapisać w nim zawartość pobrania, a następnie utworzyć znacznik zakotwiczenia z adresem URL obiektu utworzonym z Blob, ale FileSaver obsługuje to już i można było spojrzeć na źródło, jeśli naprawdę chciał.

Po prostu zmodyfikuj poniższe elementy, aby dodać pewne sprawdzenia i logikę do określania nazwy pliku/pliku i powinieneś być w stanie poradzić sobie z przypadkiem użycia.

<script src="cdn-to-FileSaver.js"></script> 

<script> 
var url = ...; 
fetch(url).then((response) => { 
    var blob = response.blob(); 
    var filename = 'song.mp4'; 

    saveAs(blob, filename); 
}); 
</script> 
+0

Sprawdzę to, kiedy dostanę trochę wolnego czasu – Anthony