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?


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");

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


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


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 })

14

Mój nowoczesny wariant:

function blob2file(blobData) {
  const fd = new FormData();
  fd.set('a', blobData);
  return fd.get('a');
}

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.