• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wysyłanie zdjęć do API

Object Storage Arubacloud
0 głosów
324 wizyt
pytanie zadane 8 grudnia 2022 w Java przez kaminie318 Bywalec (2,070 p.)

Siema. Mam problem z wysłaniem zdjęcia do API. Próbuję zrobić to w taki sposób jednak dostaję 400setkę. Wie ktoś gdzie może być problem? Oto kod:

//Backend(Java)

@CrossOrigin("*")
@RestController
public class FileController {

    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseEntity uploadFile(@RequestParam MultipartFile file) {
        logger.info(String.format("File name '%s' uploaded successfully.", file.getOriginalFilename()));
        return ResponseEntity.ok().build();
    }
}


//Frontend(React)

import axios from 'axios';

const [file, setFile] = useState();

function onFileChangeHandler(e){
      e.preventDefault();
      setFile(e.target.files[0]);
      const formData = new FormData();
      formData.append('file', file);
      axios.post("http://localhost:8080/upload", formData)
          .then(res => {
                  console.log(res.data);
                  alert("File uploaded successfully.")
          })
  };

            <div>
              <input type="file" onChange={onFileChangeHandler} />
              <br></br><br></br>
              <img src={file} />
            </div>

Z góry dzięki za pomoc

1 odpowiedź

+1 głos
odpowiedź 8 grudnia 2022 przez Wiciorny Ekspert (269,710 p.)
edycja 8 grudnia 2022 przez Wiciorny

400 w tym wypadku Bad Request, będzie związana z typem danych
consumes = MediaType.MULTIPART_FORM_DATA_VALUE

Jak wygląda obiekt który przesyłasz, mam na myśli od strony backendowej obiekt z @RequestBody MultipartFile (klasa jaka ma reprezentacje, albo encja nie wiem czym to u Ciebie jest)

Bo w kodzie po stronie klienta widzę obiekt "formData", zgodność musi być nie tylko w kwestii pól, ale zgodność musi być na poziomie typu danych tego pola, jeśli np masz encje z polem typu Date, to nie moze to być "stringowa data" zapisana ciągiem. Chyba, że określisz dokładną strukture obiektu " jaki ma być przekazany" wykorzystując do tego jakiś mapper np
https://www.baeldung.com/jackson-object-mapper-tutorial
i implementując odpowiednią serializacje.

Teraz widzę korzystasz z adnotacji @RequestParam o ile prowadzisz to w taki sposób to
 

1, @ RequestParam
Wartosci przekazywane przez GET LUB POST SA automatycznie mapowane na typ który znajduję się po @RequestParametrze, jeśli nie korzystasz z maperów, na trasie zbierania danych są sprawdzane typy i właściwości  obiektu. Przez co każde pole tego obiektu będzie musiało mieć określony typ, a już na starcie prawdopodobnie tak nie jest chyba że korzystasz z zaimplementowanego mappera 

2, @ RequestBody

@The RequestBody annotation dane mogą zostać przekazane w postaci json formatu i konwertowane dopiero potem do typu danych który masz w Javie ( tzn tych związanych z parametrem).  Co to za różnica? A no taka, że reuqest zostanie zebrany już po stronie kontrolera i dopiero tutaj zacznie się obsługa, a nie jak w poprzednim wypadku - wyrzuci Ci bad Request, ponieważ nie jest wstanie  controler wywnioskować czy parametr który przekazujesz jest zgodny z typem który wysyłasz 

Spróbuj : 

@RequestBody MultipartFile file
komentarz 8 grudnia 2022 przez Wiciorny Ekspert (269,710 p.)
Przypomne tylko, żę @RestController over @Controller jedynie dostarcza @ResponseBody
komentarz 8 grudnia 2022 przez kaminie318 Bywalec (2,070 p.)

Teraz dostaję 500tkę z nullPointerem, nic się nie przekazało :(

java.lang.NullPointerException: Cannot invoke "org.springframework.web.multipart.MultipartFile.getOriginalFilename()" because "file" is null

Nie wiem w ogóle czy poprawnie to robię. Moim celem jest pobranie zdjęcia dodanego do formularza i zapisanie go w bazie(PostgreSQL) ze zwierzętami. Szczerze powiedziawszy nigdy nie zapisywałem zdjęcia w bazie i trochę się z tym męczę bazując na internetowych poradnikach, w dodatku raczkuje we frontendzie.

komentarz 8 grudnia 2022 przez Wiciorny Ekspert (269,710 p.)
edycja 8 grudnia 2022 przez Wiciorny

teraz mam problem nie z Controlerem i wyołaniem rządanie, ale widać że kod działa... masz problem z serwerem bo zwraca 500 i masz informacje, że plik jest null... 
Czyli kontroler dalej nie rozumie jaki obiekt mu wysyłasz, a ja dalej nie widze jak wysyłasz obiekt. 

Sprawdz po stronie klienta 
 

const formData = new FormData();
      formData.append('file', file);

czy faktycznie przekazujesz to co przekazujesz, czy już tutaj nie jest to nulem. 
Dalej nie wiem czy korzystasz z mapera i dalej problemem będzie typ danych który przekazujesz. 

Wydaje mi się że korzystasz z czegoś, o czym nie masz totalnie pojęcia sprawdz sobie tutaj https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html

Bo ta klasa to nie "każda lepsza" na rozwiązanie 

https://www.baeldung.com/sprint-boot-multipart-requests

 

If you want to use a MultipartFile, you must use the multipart/form-data mimetype when requesting. Instead of sending the JSON as request entity, 

ale po stronie klienta nie widzę abyś wskazał jaki format danych wysyłasz  

Możesz to spróbować pominąc spróbuj  zamiast @RequestBody
 

@RequestPart(value = "file") 


Albo określasz typ po stronie KLIENTA co wysyłasz i jaki typ danych przekazujesz "jako nagłówek dodatkowy", albo skorzystaj z @RequestPart.
Albo odbieraj String po stronie javy i wysylaj to jsonem w postaci json stringa i mapuj dopiero na backendzie ze stringa 

formData.append('file', JSON.stringify(file));

// i wtedy 
@RequestPart(value = "file") String file)

i korzystasz z mapera 
TwojaKlasa file= objectMapper.readValue(file, TwojaKlasa.class)


 

komentarz 8 grudnia 2022 przez kaminie318 Bywalec (2,070 p.)
Nie korzystam z żadnego mappera na razie, wszystko co wysłałem wyżej to cały kod dotyczący tej funkcjonalności, chcę to po prostu wczytać do API na ten moment. Czyli zamiast adnotacji @RequestMapping powinienem użyć @RequestPart ? Jak ty byś zaimplementował takie wczytanie zdjęcia z formularza i zapisanie gdzieś w bazie?

Podobne pytania

+1 głos
1 odpowiedź 326 wizyt
+1 głos
1 odpowiedź 492 wizyt
pytanie zadane 18 czerwca 2022 w Java przez `Krzychuu Stary wyjadacz (13,940 p.)
0 głosów
0 odpowiedzi 763 wizyt
pytanie zadane 20 kwietnia 2017 w Java przez Jonki Dyskutant (8,180 p.)

92,551 zapytań

141,393 odpowiedzi

319,523 komentarzy

61,936 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...