Jak przekonwertować Blob do pliku w JavaScript

111

Muszę przesłać obraz na serwer NodeJS do jakiegoś katalogu. Używam connect-busboydo tego modułu węzła.

Miałem dataURLobraz, który przekonwertowałem na blob za pomocą następującego kodu:

dataURLToBlob: function(dataURL) {
    var BASE64_MARKER = ';base64,';
    if (dataURL.indexOf(BASE64_MARKER) == -1) {
        var parts = dataURL.split(',');
        var contentType = parts[0].split(':')[1];
        var raw = decodeURIComponent(parts[1]);
        return new Blob([raw], {type: contentType});
    }
    var parts = dataURL.split(BASE64_MARKER);
    var contentType = parts[0].split(':')[1];
    var raw = window.atob(parts[1]);
    var rawLength = raw.length;
    var uInt8Array = new Uint8Array(rawLength);
    for (var i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], {type: contentType});
}

Potrzebuję sposobu na przekonwertowanie obiektu BLOB na plik, aby przesłać obraz.

Czy ktoś mógłby mi w tym pomóc?

pominąć
źródło
4
Pliki to bloby, po prostu przypiąć właściwości meta i gotowe.
dandavis
1
Wartość domyślna dla obiektu BLOB podczas przesyłania to blob. Tak więc najpierw wyodrębniłem nazwę pliku, który przycinałem, a następnie nadałem to samo, filenametak aby przycięty plik podczas przesyłania go na serwer, wykonując form.append("blob",blob, filename);.
pomiń
@skip, czy moja odpowiedź poniżej pomogła? Tak, zaznacz to jako poprawną odpowiedź.
CBarr

Odpowiedzi:

150

Ta funkcja konwertuje a Blobna a Filei działa świetnie dla mnie.

Waniliowy JavaScript

function blobToFile(theBlob, fileName){
    //A Blob() is almost a File() - it's just missing the two properties below which we will add
    theBlob.lastModifiedDate = new Date();
    theBlob.name = fileName;
    return theBlob;
}

TypeScript (z poprawnymi typami)

public blobToFile = (theBlob: Blob, fileName:string): File => {
    var b: any = theBlob;
    //A Blob() is almost a File() - it's just missing the two properties below which we will add
    b.lastModifiedDate = new Date();
    b.name = fileName;

    //Cast to a File() type
    return <File>theBlob;
}

Stosowanie

var myBlob = new Blob();

//do stuff here to give the blob some data...

var myFile = blobToFile(myBlob, "my-image.png");
CBarr
źródło
3
Myślę, że rzutowanie powinno nastąpić najpierw, więc nie musisz używać anyw TypeScript. Zobacz ten przykład.
styfle
2
To nie działa do wszystkich celów. Dodanie tego „pliku” do wywołania Ajax nie ustawi poprawnie nazwy pliku.
Jacob Poul Richardt
12
To nie jest dobre rozwiązanie, wyprodukowany obiekt nadal jest plamą.
czupe
4
Wystarczy dodać b.__proto__ = File.prototype, a roztwór staje się sen, że nawet sztuczki b instanceOf Filedotrue
manuelnaranjo
3
Nie powinno to być akceptowaną odpowiedzią, powinno być stackoverflow.com/a/53205768/2557517 lub stackoverflow.com/a/31663645/2557517 .
Kira
204

Możesz użyć konstruktora File:

var file = new File([myBlob], "name");

Zgodnie ze specyfikacją w3 doda to bajty, które zawiera obiekt BLOB, do bajtów nowego obiektu File i utworzy plik o określonej nazwie http://www.w3.org/TR/FileAPI/#dfn-file

Joshua P. Nixon
źródło
2
Właśnie tego szukałem, jedyną różnicą jest to, że pierwszy argument jest w rzeczywistości tablicą, więc użyłem go jako: var file = new File ([myBlob], "name");
Michaeldcooney
1
Tak. Ja też szukam tego rozwiązania. Serwer Stamplay nie może pobrać nazwy pliku z obiektu blob. Więc muszę przekonwertować go z powrotem do pliku. Ale Safari nie obsługuje API plików ... teraz wróć do 0 :(
Hugh Hou
4
Konstruktory plików nie działają np. W PhantomJS:TypeError: FileConstructor is not a constructor (evaluating 'new File([''], 'file.pdf', {'size': 1000, 'type': 'application/pdf'})')
bkimminich
7
Edge ma obecnie (04.10.2017) błąd uniemożliwiający użycie tego konstruktora. developer.microsoft.com/en-us/microsoft-edge/platform/issues/…
Rik Martins
8
Pamiętaj, aby dodać typ pliku, w przeciwnym razie nie będzie działać poprawnie. nowy plik ([myBlob], "name", {type: "image / jpeg",});
BernardA,
34

Odpowiedź Joshua P Nixona jest poprawna, ale musiałem również ustawić datę ostatniej modyfikacji. więc oto kod.

var file = new File([blob], "file_name", {lastModified: 1534584790000});

1534584790000 to uniksowa sygnatura czasowa dla „ GMT: sobota, 18 sierpnia 2018 9:33:10

mili
źródło
3
Punkty za niezłomność instanceofjak przyjęta odpowiedź
Matt Jensen
15

Aby działało, musiałem jawnie podać typ, chociaż jest on zawarty w obiekcie blob, robiąc to:

const file = new File([blob], 'untitled', { type: blob.type })
Alexandre Daubricourt
źródło
14

Mój nowoczesny wariant:

function blob2file(blobData) {
  const fd = new FormData();
  fd.set('a', blobData);
  return fd.get('a');
}
DAVID _
źródło
2
Aby dodać nazwę pliku do pliku wynikowego, użyj:fd.set('a', blobData, 'filename')
joaoguerravieira
W niektórych urządzeniach z systemem IOS zawodzi, gdyfd.set
Śpiewaj
dzięki. to działa, teraz nie muszę konwertować obiektu BLOB do pliku.
xreyc_developer22
2

Użyj saveAsw projekcie FileSaver.js github.

FileSaver.jsimplementuje saveAs()interfejs FileSaver w przeglądarkach, które nie obsługują go natywnie.

Muzułmanin Shahsavan
źródło
2

Maszynopis

public blobToFile = (theBlob: Blob, fileName:string): File => {       
    return new File([theBlob], fileName, { lastModified: new Date().getTime(), type: theBlob.type })
}

Javascript

function blobToFile(theBlob, fileName){       
    return new File([theBlob], fileName, { lastModified: new Date().getTime(), type: theBlob.type })
}

Wynik

zrzut ekranu

File {name: "fileName", lastModified: 1597081051454, lastModifiedDate: Mon Aug 10 2020 19:37:31 GMT+0200 (Eastern European Standard Time), webkitRelativePath: "", size: 601887, …}
lastModified: 1597081051454
lastModifiedDate: Mon Aug 10 2020 19:37:31 GMT+0200 (Eastern European Standard Time) {}
name: "fileName"
size: 601887
type: "image/png"
webkitRelativePath: ""
__proto__: File
Hossam EL-Kashef
źródło