Jump to content

Atualizar o src do input file clicado


Bill Fender

Recommended Posts

Olá, tudo bem?

Esse é meu primeiro post aqui, então não sei como postar o código. Vou tentar explicar.

Eu tenho vários input files em uma página de projeto de upload de imagens.

O objetivo é redimensionar a imagem para 800 por 600 antes do upload. Isso já está ok.

Agora preciso atualizar o src do input file clicado (target.src) com essas dimensões para enviar para o recebe.php.

 

Agradeço desde já

 

 

<form action="./recebe.php" method="post" id="form" enctype="multipart/form-data">

<input type="file" accept="image/*" id="image1" name="img1[]">
<br><br>

<input type="file" accept="image/*" id="image2" name="img1[]">
<br><br>



<input type="file" accept="image/*" id="image3" name="img2[]">
<br><br>

<input type="file" accept="image/*" id="image4" name="img2[]">
<br><br>



<button> Enviar </button>

</form>



<script type="text/javascript">



let form = document.querySelector("#form");



form .addEventListener("change", (e)=>{

  e.preventDefault();

var file = e.target.files[0];//input clicado

     const reader = new FileReader();

     reader.readAsDataURL(file);
     reader.name = file.name;
     reader.size = file.size;


    reader.onload = function (event)
    {
      var img = new Image();
      img.src = event.target.result;

     img.onload = function (el)
     {
     	 var elem = document.createElement('canvas');

      elem.width = 800;
      elem.height = 600;


      var ctx = elem.getContext('2d');
      ctx.drawImage(el.target, 0, 0, elem.width, elem.height);

      
   	   var srcEncoded = ctx.canvas.toDataURL('image/jpeg', 0.5);

   	   console.log(srcEncoded);//Aqui está okay

   	   e.target.src = srcEncoded; //Estou aqui. Mas não deu certo, o recebe.php faz upload da imagem original.

				//Preciso atualizar o próprio input file clicado para enviar essa imagem com essas dimensões 800x600

				//Com o mesmo input file que é clicado

					//Issoctx.canvas.toDataURL('image/jpeg', 0.5); retorna obase64, não sei se é isso mesmo.
     }
    }
});

</script>

==============Arquivo recebe.php

<?php

//Aqui como eu faço para ele fazer o upload
// O $_FILES['img1']['tmp_name'][0] , por exemplo, recebera o data:image/jpeg;base64,....
//Como converto ele para imagem jpeg

move_uploaded_file($_FILES['img1']['tmp_name'][0], $_FILES['img1']['name'][0]);
move_uploaded_file($_FILES['img1']['tmp_name'][1], $_FILES['img1']['name'][1]);


move_uploaded_file($_FILES['img2']['tmp_name'][0], $_FILES['img2']['name'][0]);
move_uploaded_file($_FILES['img2']['tmp_name'][1], $_FILES['img2']['name'][0]);

?>

 

Edited by Bill Fender
Mais detalhes e corregir
Link to comment
Share on other sites

Em 09/07/2024 às 05:42, M6 disse:

Pelo que compreendi, queres redimensionar uma imagem no cliente usando código que executa no servidor, é isso?

Olá.

....queres redimensionar uma imagem no cliente....isso está okay. Ela faz nessa parte do código:

ctx.drawImage(el.target, 0, 0, elem.width, elem.height);

var srcEncoded = ctx.canvas.toDataURL('image/jpeg', 0.5);

 

Agora preciso atualizar o input file ( o target, ou seja, o input que dispara o evento), com o resultado srcEncoded para enviar para o servidor essas novas dimensões.

Esqueci de mencionar, nas ferramentas de desenvolvedor do chrome o srcEncoded retorna data:image/jpeg;base64,/9j/4AA.... com as dimensões corretas. Então ele está como eu preciso.

Como pode ver no código, tentei assim e.target.src = srcEncoded; mas não deu certo.

Os move_uploaded_file($_FILES['img1']['tmp_name'][0], $_FILES['img1']['name'][0]); recebem a imagem original ainda, também não deu certo ainda.

 

Parece que o enclave está aqui  e.target.src = srcEncoded;

Obrigado pela ajuda.

Se tiver mais alguma ajuda agradeço.

 

Edited by Bill Fender
Tinha esquecido de mencionar o dataimage
Link to comment
Share on other sites

Olá!
Acredito fortemente que não seja possível alterar o source file de um html input (por questão de segurança)
Mas podes fazer teu upload via ajax. veja a sugestão:

Estrutura do projeto:
05aKMd7xR4uir9fLKopxTQ.png


Arquivo index.html

<head>
  <style>
    #messager {
      font-family: monospace;
      white-space: pre;
    }
  </style>
</head>
<form action="./recebe.php" method="post" id="form">

  <input type="file" accept="image/*" name="img1[]">
  <br><br>

  <input type="file" accept="image/*" name="img1[]">
  <br><br>

  <input type="file" accept="image/*" name="img2[]">
  <br><br>

  <input type="file" accept="image/*" name="img2[]">
  <br><br>

  <button> Enviar </button>

</form>

<p id="messager"></p>

<script type="text/javascript">

  let fData = new FormData();

  form.onchange = async function ({ target }) {

    const file = target.files[0];

    if (!file) {
      return;
    }

    const croppedImage = await cropImage(file);

    fData.append(target.name, croppedImage, file.name);
  }

  form.onsubmit = async function (e) {
    e.preventDefault();

    const response = await fetch(form.getAttribute('action'), {
      method: form.getAttribute('method'),
      body: fData
    });

    let images = ''

    const data = await response.json();

    if (response.ok) {
      fData = new FormData();
      form.reset();
      for (const key of Object.keys(data)) {
        for (const img of data[key]) {
          images += `<img src="assets/images/${img.name}"><br>`
        }
      }
    } else {
    }

    messager.innerHTML = JSON.stringify({ response: data }, null, 2) + images

  }

  const cropImage = (file, size = { width: 800, height: 600 }, quality = .5) => {
    return new Promise((resolve, reject) => {

      const reader = new FileReader();
      const img = new Image();

      reader.onload = function (e) {
        img.src = e.target.result;
      };

      img.onload = () => {
        const canvas = document.createElement('canvas');

        canvas.width = size.width;
        canvas.height = size.height;

        const ctx = canvas.getContext('2d');

        let srcX, srcY, srcWidth, srcHeight;
        const aspectRatio = img.width / img.height;
        const targetRatio = size.width / size.height;

        if (aspectRatio > targetRatio) {
          // Imagem horizontal
          srcHeight = img.height;
          srcWidth = img.height * targetRatio;
          srcX = (img.width - srcWidth) / 2;
          srcY = 0;
        } else {
          // Imagem vertial
          srcWidth = img.width;
          srcHeight = img.width / targetRatio;
          srcX = 0;
          srcY = (img.height - srcHeight) / 2;
        }

        ctx.drawImage(img, srcX, srcY, srcWidth, srcHeight, 0, 0, size.width, size.height);

        canvas.toBlob(blob => {
          resolve(new File([blob], file.name, {
            type: 'image/jpeg',
            lastModified: Date.now()
          }));
        }, 'image/jpeg', quality);
      }

      reader.readAsDataURL(file);

    })
  }

</script>

Arquivo recebe.php:

<?php

header('Content-Type: application/json');

if(count($_FILES)) {

  $files = array_map(function ($file) {
    $imageData = [];

    foreach(array_keys($file['name']) as $key) {
      $imageData[] = [
        'name'      => $file['name'][$key],
        'full_path' => $file['full_path'][$key],
        'type'      => $file['type'][$key],
        'tmp_name'  => $file['tmp_name'][$key],
        'error'     => $file['error'][$key],
        'size'      => $file['size'][$key],
      ];
    }

    return $imageData;
  }, $_FILES);

  foreach($files as $key => $v) {

    $data[$key] = [];
    foreach($v as $i => $file) {
      $fileData = getimagesize($file['tmp_name']);
      move_uploaded_file($file['tmp_name'], 'assets/images/' . $file['name']);

      $data[$key][$i]['name']       = $file['name'];
      $data[$key][$i]['dimensions'] = $fileData[3];
      $data[$key][$i]['size']       = $file['size'];
    }
  }

  exit(json_encode($data));
}
http_response_code(400);
exit(json_encode('Nenhum arquivo enviado'));

 

Link to comment
Share on other sites

Não é possível fazer o que queres, pois isso implicaria que, através do browser poderias manipular ficheiros locais do dispositivo.

O que podes fazer, que é o normal, é fazeres upload do ficheiro para o servidor e depois, do lado do servidor, fazeres o redimensionamento da imagem.

10 REM Generation 48K!
20 INPUT "URL:", A$
30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50
40 PRINT "404 Not Found"
50 PRINT "./M6 @ Portugal a Programar."

 

Link to comment
Share on other sites

Em 10/07/2024 às 02:14, washalbano disse:

Olá!
Acredito fortemente que não seja possível alterar o source file de um html input (por questão de segurança)
Mas podes fazer teu upload via ajax. veja a sugestão:

Estrutura do projeto:
05aKMd7xR4uir9fLKopxTQ.png


Arquivo index.html

<head>
  <style>
    #messager {
      font-family: monospace;
      white-space: pre;
    }
  </style>
</head>
<form action="./recebe.php" method="post" id="form">

  <input type="file" accept="image/*" name="img1[]">
  <br><br>

  <input type="file" accept="image/*" name="img1[]">
  <br><br>

  <input type="file" accept="image/*" name="img2[]">
  <br><br>

  <input type="file" accept="image/*" name="img2[]">
  <br><br>

  <button> Enviar </button>

</form>

<p id="messager"></p>

<script type="text/javascript">

  let fData = new FormData();

  form.onchange = async function ({ target }) {

    const file = target.files[0];

    if (!file) {
      return;
    }

    const croppedImage = await cropImage(file);

    fData.append(target.name, croppedImage, file.name);
  }

  form.onsubmit = async function (e) {
    e.preventDefault();

    const response = await fetch(form.getAttribute('action'), {
      method: form.getAttribute('method'),
      body: fData
    });

    let images = ''

    const data = await response.json();

    if (response.ok) {
      fData = new FormData();
      form.reset();
      for (const key of Object.keys(data)) {
        for (const img of data[key]) {
          images += `<img src="assets/images/${img.name}"><br>`
        }
      }
    } else {
    }

    messager.innerHTML = JSON.stringify({ response: data }, null, 2) + images

  }

  const cropImage = (file, size = { width: 800, height: 600 }, quality = .5) => {
    return new Promise((resolve, reject) => {

      const reader = new FileReader();
      const img = new Image();

      reader.onload = function (e) {
        img.src = e.target.result;
      };

      img.onload = () => {
        const canvas = document.createElement('canvas');

        canvas.width = size.width;
        canvas.height = size.height;

        const ctx = canvas.getContext('2d');

        let srcX, srcY, srcWidth, srcHeight;
        const aspectRatio = img.width / img.height;
        const targetRatio = size.width / size.height;

        if (aspectRatio > targetRatio) {
          // Imagem horizontal
          srcHeight = img.height;
          srcWidth = img.height * targetRatio;
          srcX = (img.width - srcWidth) / 2;
          srcY = 0;
        } else {
          // Imagem vertial
          srcWidth = img.width;
          srcHeight = img.width / targetRatio;
          srcX = 0;
          srcY = (img.height - srcHeight) / 2;
        }

        ctx.drawImage(img, srcX, srcY, srcWidth, srcHeight, 0, 0, size.width, size.height);

        canvas.toBlob(blob => {
          resolve(new File([blob], file.name, {
            type: 'image/jpeg',
            lastModified: Date.now()
          }));
        }, 'image/jpeg', quality);
      }

      reader.readAsDataURL(file);

    })
  }

</script>

Arquivo recebe.php:

<?php

header('Content-Type: application/json');

if(count($_FILES)) {

  $files = array_map(function ($file) {
    $imageData = [];

    foreach(array_keys($file['name']) as $key) {
      $imageData[] = [
        'name'      => $file['name'][$key],
        'full_path' => $file['full_path'][$key],
        'type'      => $file['type'][$key],
        'tmp_name'  => $file['tmp_name'][$key],
        'error'     => $file['error'][$key],
        'size'      => $file['size'][$key],
      ];
    }

    return $imageData;
  }, $_FILES);

  foreach($files as $key => $v) {

    $data[$key] = [];
    foreach($v as $i => $file) {
      $fileData = getimagesize($file['tmp_name']);
      move_uploaded_file($file['tmp_name'], 'assets/images/' . $file['name']);

      $data[$key][$i]['name']       = $file['name'];
      $data[$key][$i]['dimensions'] = $fileData[3];
      $data[$key][$i]['size']       = $file['size'];
    }
  }

  exit(json_encode($data));
}
http_response_code(400);
exit(json_encode('Nenhum arquivo enviado'));

 

Obrigado pela ajuda. Mas não tenho familiaridade com json. Não consegui adaptar para minha necessidade.

Vou retornar para meu script para tentar de outra maneira. 

Mas surgiu um novo problema para ele, alguns usuários estão enviando imagem jpg com essa codificação data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1...... Acredito que seja imagem codificada na base64, é isso?

A partir dessa parte do scfript img.src = event.target.result; retorna apenas data:image/jpeg;base64, até a vírgula. E o restante do script buga.

Tem como verificar isso e tratar, se a imagem está nessa base64 antes do reader.onload = function (event)...?

Qual seria a melhor solução?

Obrigado.

 

Link to comment
Share on other sites

Em 12/07/2024 às 19:35, MentorDuncan disse:

base64 é uma string
não faz sentido enviar via input:file, melhor usar um textarea

Olá.

Obrigado pela ajuda.

 

Pedi um var_dump ($_FILES); do servidor e o retorno é esse

["name"]=> string(36) "2d88ef370b30871fb845a902bd4afaf3.jpg" ["full_path"]=> string(36) "2d88ef370b30871fb845a902bd4afaf3.jpg" ["type"]=> string(24) "application/octet-stream" ["tmp_name"]=> string(14) "/tmp/phpLadv65" ["error"]=> int(0) ["size"]=> int(31907) }

 

Para cada uma das images.

Criei um input file multiple para receber o canvas para contornar, e deu certo. Envio esse input file para o servidor.

Muito obrigado.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.