Страницы

Поиск по вопросам

Показаны сообщения с ярлыком blob. Показать все сообщения
Показаны сообщения с ярлыком blob. Показать все сообщения

среда, 26 февраля 2020 г.

Не получается сохранить pdf на стороне клиента

#javascript #php #pdf #blob #mpdf


Приходит ответ с сервера. в ответе pdf-файл (содержание обрезанное):



Формирую файл на сервере (Laravel):

public function getTaskOrderLabel (Request $request) {

  $mpdf = new \Mpdf\Mpdf($props);
  $mpdf->showImageErrors = true;

  $props = [
    //'debug' => true,
    'tempDir' => '/home/mpdf',
    'format' => [100,20],
    'margin_left' => 0,
    'margin_right' => 0,
    'margin_top' => 0,
    'margin_bottom' => 0,
    'margin_header' => 0,
    'margin_footer' => 0,
  ];

  foreach ($ptfe as $el) {

    // Наполняем данными
    // ...
    // Формируем стили

    $mpdf->WriteHTML($style, \Mpdf\HTMLParserMode::HEADER_CSS);
    $mpdf->WriteHTML($page, \Mpdf\HTMLParserMode::HTML_BODY);
    $mpdf->AddPage();
  }

  $mpdf->Output();

}


Сохраняю файл:

.then(response => {
  console.log(response.data);
  let file = new Blob([response.data], {type: 'application/pdf'});
  let fileURL = URL.createObjectURL(file);
  window.open(fileURL);
 })


Файл создаётся и сохраняется, но в нём нет данных, но есть количество страниц в документе.
В чём проблема?
    


Ответы

Ответ 1



В вашем случае в переменной response.data скорее всего содержится base64 строка с содержимым файла, так как у вас pdf-файл (бинарный), то и Blob объект нужно создавать из бинарных данных. Используйте параметр responseType для того чтобы указать в какой формат axios должен конвертировать ваш ответ от сервера. Ниже я привёл 2 варианта конвертации base64 в файл. Вариант 1) responseType: 'blob' - axios сам создаст Blob файл и запишет его в переменную response.data. Вариант 2) responseType: 'arraybuffer' - axios преобразует ответ в бинарные данные, объект ArrayBuffer и запишет его в переменную response.data. // use responseType: 'blob' axios({ url: 'http://localhost/download_pdf', method: 'GET', responseType: 'blob', // <-- }).then(response => { const blob_file = response.data; const file_url = URL.createObjectURL(blob_file); window.open(file_url); // open file in new tab }); // or use responseType: 'arraybuffer' axios({ url: 'http://localhost/download_pdf', method: 'GET', responseType: 'arraybuffer', // <-- }).then(response => { const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'custom_filename.pdf'); // set custom file name document.body.appendChild(link); link.click(); // force download file without open new tab }); // backend on the Laravel (for example) // file web.php Route::get('/download_pdf', function () { $filename = 'labels.pdf'; $pathToFile = public_path().'/'.$filename; return Response::make(file_get_contents($pathToFile), 200, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="'.$filename.'"' ]); }); // несколько ссылок с простыми pdf для тренировок // http://www.orimi.com/pdf-test.pdf // http://www.pdf995.com/samples/pdf.pdf // https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf // http://www.africau.edu/images/default/sample.pdf Подробнее.

четверг, 23 января 2020 г.

Загрузка видео на сайт в виде Blob

#javascript #html #потоки_данных #youtube #blob


Если посмотреть на youtube.com, то url у любого видео выглядит вот так: blob:https://www.youtube.com/17c9289e-4450-4ea0-a0bd-56570172d62a.
Это говорит о том, что видео было загружено в виде бинарного объекта и обработано функцией
window.URL.createObjectURL(). 

Я не понимаю как они это делают со всем видео целиком, ведь оно большого размера,
а url у видео не меняется до конца времени проигрывания (если плеер не решил поменять
качество или сервер). 

Вопрос заключается в том, как загружать видео на клиент в виде Blobа так, как делают
это на youtube.com.
    


Ответы

Ответ 1



D-side, подсказал посмотреть в сторону MediaSource. Этот объект позволяет задать url объекта video как window.URL.createObjectURL(mediaSource). Это позволяет задавать источник в виде Blob'а, но с одним важным свойством: мы можем догружать данные в mediaSource, например, при получении продолжения видео по AJAX или каким-либо другим способом. Пример работы с MDN: var video = document.querySelector('video'); var assetURL = 'frag_bunny.mp4'; var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'; if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) { var mediaSource = new MediaSource; video.src = URL.createObjectURL(mediaSource); mediaSource.addEventListener('sourceopen', sourceOpen); } else { console.error('Unsupported MIME type or codec: ', mimeCodec); } function sourceOpen (_) { var mediaSource = this; var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec); fetchData(assetURL, function (buf) { sourceBuffer.addEventListener('updateend', function (_) { mediaSource.endOfStream(); video.play(); }); sourceBuffer.appendBuffer(buf); }); }; Метод рабочий, но есть свои приколы, например, 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"' - единственный майм кодек, который работает и в Chrome и в Mozilla. Если хочется работать с webm: 'video/webm; codecs="vp9,vorbis"' в Mozilla, то придется включать флаг в about:config, что не очень приятно для пользователя.

среда, 18 декабря 2019 г.

Загрузка файла (картинки - jpg в BLOB-поле)

#mysql #delphi #blob


Пытаюсь загрузить файл в БД (MySQL), в blob-поле (маленькую, до 50kb картинку - формат
jpg).

Но вот что-то у меня идёт не так:

var
  ImgPath: String;

begin  
  ImgPath:=ExtractFilePath(ParamStr(0))+'data\photo.jpg';
  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.ADD('UPDATE exam_users SET `photo`=(:fphoto) WHERE `number` = 94');
  ADOQuery1.parameters.parambyname('fphoto').LoadFromFile(ImgPath, ftBlob);

  ADOQuery1.ExecSQL;
  ADOQuery1.Close;
end;


также пробовал и так:

var
  ImgPath: String;
  fs:TFileStream;

begin    
  ImgPath:=ExtractFilePath(ParamStr(0))+'data\photo.jpg';
  fs :=TFileStream.Create(ImgPath, fmOpenRead or fmShareDenyWrite);
  ADOQuery1.SQL.ADD('UPDATE exam_users SET `photo`=(:fphoto) WHERE `number` = 94');
  ADOQuery1.Parameters.ParamByName('fphoto').LoadFromStream(fs, ftBlob);
  ADOQuery1.ExecSQL;
  fs.Free;
  ADOQuery1.Close;
end;


Все эти два примера выдают одну ошибку:


  Project Project2.exe raised exception class EOleException with message 'Аргументы
имеют неверный тип, выходят за пределы допустимого диапазона или вступают в конфликт
друг с другом'.

    


Ответы

Ответ 1



Что то мне подсказывает что тип поля не совсем ftBlob, я бы поэкспериментировал с другими значениями. Я так понимаю у Вас в базе тип поля text? При работе с потоком еще попробуйте установить позицию в 0. fs := TFileStream.Create... fs.Position = 0; На крайний случай можно написать как то так. ImgPath := ExtractFilePath(ParamStr(0))+'data\photo.jpg'; ADOQuery1.SQL.Text := 'select `photo` from exam_users where `number` = 94'; ADOQuery1.Open; TBlobField(ADOQuery1.FieldByName('photo')).LoadFromFile('c:\sample_2.jpg'); Но это не решает Вашу проблему. И если в базе есть уже данные, они сперва тянутся на клиент, а потом обновляются.

Ответ 2



Вернулся снова в проекте к этому вопросу. Оказывается если в первом примере данное сообщение при компиляции проекта игнорировать, то всё прекрасно записывается в БД! А когда файл проекта скопмилирован и просто запускается на исполнение, то ни какого сообщения программа не выдаёт и всё срабатывает на 100%. Файл без каких-либо ошибок загружается в Blob-поле БД. Так что: ImgPath:=ExtractFilePath(ParamStr(0))+'data\photo.jpg'; ADOQuery1.Close; ADOQuery1.SQL.Clear; ADOQuery1.SQL.ADD('UPDATE exam_users SET `photo`=(:blob_photo) WHERE `number` = 94'); ADOQuery1.parameters.parambyname('blob_photo').LoadFromFile(ImgPath, ftBlob); ADOQuery1.ExecSQL; ADOQuery1.Close; работоспособный код.

понедельник, 18 марта 2019 г.

Загрузка видео на сайт в виде Blob

Если посмотреть на youtube.com, то url у любого видео выглядит вот так: blob:https://www.youtube.com/17c9289e-4450-4ea0-a0bd-56570172d62a. Это говорит о том, что видео было загружено в виде бинарного объекта и обработано функцией window.URL.createObjectURL().
Я не понимаю как они это делают со всем видео целиком, ведь оно большого размера, а url у видео не меняется до конца времени проигрывания (если плеер не решил поменять качество или сервер).
Вопрос заключается в том, как загружать видео на клиент в виде Blobа так, как делают это на youtube.com.


Ответ

D-side, подсказал посмотреть в сторону MediaSource. Этот объект позволяет задать url объекта video как window.URL.createObjectURL(mediaSource). Это позволяет задавать источник в виде Blob'а, но с одним важным свойством: мы можем догружать данные в mediaSource, например, при получении продолжения видео по AJAX или каким-либо другим способом.
Пример работы с MDN:
var video = document.querySelector('video');
var assetURL = 'frag_bunny.mp4'; var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) { var mediaSource = new MediaSource; video.src = URL.createObjectURL(mediaSource); mediaSource.addEventListener('sourceopen', sourceOpen); } else { console.error('Unsupported MIME type or codec: ', mimeCodec); }
function sourceOpen (_) { var mediaSource = this; var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec); fetchData(assetURL, function (buf) { sourceBuffer.addEventListener('updateend', function (_) { mediaSource.endOfStream(); video.play(); }); sourceBuffer.appendBuffer(buf); }); };
Метод рабочий, но есть свои приколы, например, 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"' - единственный майм кодек, который работает и в Chrome и в Mozilla. Если хочется работать с webm: 'video/webm; codecs="vp9,vorbis"' в Mozilla, то придется включать флаг в about:config, что не очень приятно для пользователя.

понедельник, 29 октября 2018 г.

Загрузка файла (картинки - jpg в BLOB-поле)

Пытаюсь загрузить файл в БД (MySQL), в blob-поле (маленькую, до 50kb картинку - формат jpg).
Но вот что-то у меня идёт не так:
var ImgPath: String;
begin ImgPath:=ExtractFilePath(ParamStr(0))+'data\photo.jpg'; ADOQuery1.Close; ADOQuery1.SQL.Clear; ADOQuery1.SQL.ADD('UPDATE exam_users SET `photo`=(:fphoto) WHERE `number` = 94'); ADOQuery1.parameters.parambyname('fphoto').LoadFromFile(ImgPath, ftBlob);
ADOQuery1.ExecSQL; ADOQuery1.Close; end;
также пробовал и так:
var ImgPath: String; fs:TFileStream;
begin ImgPath:=ExtractFilePath(ParamStr(0))+'data\photo.jpg'; fs :=TFileStream.Create(ImgPath, fmOpenRead or fmShareDenyWrite); ADOQuery1.SQL.ADD('UPDATE exam_users SET `photo`=(:fphoto) WHERE `number` = 94'); ADOQuery1.Parameters.ParamByName('fphoto').LoadFromStream(fs, ftBlob); ADOQuery1.ExecSQL; fs.Free; ADOQuery1.Close; end;
Все эти два примера выдают одну ошибку:
Project Project2.exe raised exception class EOleException with message 'Аргументы имеют неверный тип, выходят за пределы допустимого диапазона или вступают в конфликт друг с другом'.


Ответ

Вернулся снова в проекте к этому вопросу. Оказывается если в первом примере данное сообщение при компиляции проекта игнорировать, то всё прекрасно записывается в БД! А когда файл проекта скопмилирован и просто запускается на исполнение, то ни какого сообщения программа не выдаёт и всё срабатывает на 100%. Файл без каких-либо ошибок загружается в Blob-поле БД. Так что:
ImgPath:=ExtractFilePath(ParamStr(0))+'data\photo.jpg'; ADOQuery1.Close; ADOQuery1.SQL.Clear;
ADOQuery1.SQL.ADD('UPDATE exam_users SET `photo`=(:blob_photo) WHERE `number` = 94'); ADOQuery1.parameters.parambyname('blob_photo').LoadFromFile(ImgPath, ftBlob);
ADOQuery1.ExecSQL; ADOQuery1.Close;
работоспособный код.