Как преобразовать Blob в файл в JavaScript

111

Мне нужно загрузить изображение на сервер NodeJS в какой-то каталог. Для этого я использую connect-busboyмодуль узла.

У меня был dataURLобраз, который я преобразовал в blob, используя следующий код:

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

Мне нужен способ преобразовать большой двоичный объект в файл для загрузки изображения.

Может ли кто-нибудь помочь мне с этим?

пропускать
источник
4
Файлы - это большие двоичные объекты, просто добавьте мета-свойства, и все готово.
dandavis
1
Значение по умолчанию для большого двоичного объекта при его загрузке - blob. Итак, я сначала извлек имя файла, который я обрезал, а затем дал то же самое, filenameчтобы обрезать файл, загружая его на сервер путем выполнения form.append("blob",blob, filename);.
пропустить
@skip помог мой ответ ниже? Так, отметьте, пожалуйста, правильный ответ.
CBarr

Ответы:

150

Эта функция преобразует a Blobв a, Fileи у меня она отлично работает.

Ванильный 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 (с правильной типизацией)

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

использование

var myBlob = new Blob();

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

var myFile = blobToFile(myBlob, "my-image.png");
CBarr
источник
3
Я думаю, что приведение должно произойти первым, поэтому вам не нужно использовать anyTypeScript. См. Этот пример.
Styfle
3
Это не работает для всех целей. Добавление этого «файла» к вызову ajax не приведет к правильной установке имени файла.
Джейкоб Пол Ричардт
13
Это не лучшее решение, созданный объект по-прежнему является каплей.
czupe
4
Просто добавьте b.__proto__ = File.prototype, и ваше решение становится мечтой , что даже трюки b instanceOf Fileнаtrue
manuelnaranjo
3
Это не должен быть принятый ответ, должно быть stackoverflow.com/a/53205768/2557517 или stackoverflow.com/a/31663645/2557517 .
Кира
204

Вы можете использовать конструктор файлов:

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

Согласно спецификации w3, это добавит байты, содержащиеся в большом двоичном объекте, к байтам для нового объекта File, и создаст файл с указанным именем http://www.w3.org/TR/FileAPI/#dfn-file

Джошуа П. Никсон
источник
2
Это то, что я искал, с той лишь разницей, что первый аргумент на самом деле является массивом, поэтому я использовал его как: var file = new File ([myBlob], "name");
Michaeldcooney
1
Да. Я тоже ищу это решение. Сервер Stamplay не может получить имя файла из объекта blob. Поэтому мне нужно преобразовать его обратно в файл. Но Safari не поддерживает файловый API ... Вернемся к 0 сейчас :(
Хью Хоу,
4
Конструкторы файлов не работают, например, в PhantomJS:TypeError: FileConstructor is not a constructor (evaluating 'new File([''], 'file.pdf', {'size': 1000, 'type': 'application/pdf'})')
bkimminich
7
В Edge в настоящее время (2017-10-04) есть ошибка, которая не позволяет использовать этот конструктор. developer.microsoft.com/en-us/microsoft-edge/platform/issues/…
Рик Мартинс,
8
Обязательно добавьте тип файла, иначе он не будет работать должным образом. новый файл ([myBlob], "name", {type: "image / jpeg",});
BernardA 07
34

Ответ Джошуа П. Никсона правильный, но мне также пришлось установить дату последнего изменения. так вот код.

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

1534584790000 - это временная метка unix для « GMT: суббота, 18 августа 2018 г., 9:33:10 AM ».

мили
источник
3
Очки за то, что не ломались, instanceofкак принятый ответ
Мэтт Дженсен
15

Чтобы я работал, мне пришлось явно указать тип, хотя он содержится в большом двоичном объекте:

const file = new File([blob], 'untitled', { type: blob.type })
Александр Добрикур
источник
14

Мой современный вариант:

function blob2file(blobData) {
  const fd = new FormData();
  fd.set('a', blobData);
  return fd.get('a');
}
ДЭВИД _
источник
2
Чтобы добавить имя файла к полученному файлу, используйте:fd.set('a', blobData, 'filename')
joaoguerravieira
Он не работает в некоторых устройствах IOS, когдаfd.set
Пойте
Спасибо. это работает, теперь мне не нужно преобразовывать blob в файл.
xreyc_developer22
2

Используйте saveAsв проекте Github FileSaver.js.

FileSaver.jsреализует saveAs()интерфейс FileSaver в браузерах, которые его не поддерживают.

Мусульманин Шахсаван
источник
2

Машинопись

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

Вывод

Скриншот

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
Хоссам Эль-Кашеф
источник