SpringBoot REST API+MyBatis+Vue.js 3 file upload

탱귤생귤·2023년 11월 20일

Vue.js

목록 보기
3/4

What I wanted to do

  1. At the Vue, select the file to upload.
  2. After writing the form, click the button to send to POST.
  3. At the StringBoot, it get the object and the img.
  4. Get the path to save the img and make a new directory based on the userId and save the img.
  5. Save the img name to the diary(dto) and do the logic of the model.

Problems while writing the code

FE

Should I use the form tag?
It was confusing whether I should use form tag or not. Because I didn't want to use it. The answer was NO. input type="file" was enough.

<div>
  <label for="img">사진첨부 : </label>
  <input type="file" id="img" name="img" @change="imgUpload" accept="image/*" />
</div>

Getting the value of the selected IMG
It was printed out on the console, but I couldn't extract it.
const file = e.target.files[0]; This is the answer.

//사진 업로드
const formData = new FormData();
const previewImage = ref("");
const imgUpload = function (e) {
  const file = e.target.files[0];
  if (file) {
    const reader = new FileReader();
    reader.onload = (e) => {
    	previewImage.value = e.target.result;
    };
    reader.readAsDataURL(file);
    formData.append("img", file);
  }
};

reader is for the image preview. I appended file as a value of "img" key in the formData. The key should be same as the Spring method's parameter's name.

How should I send the object?
At first I tried sending the object as JSON format and failed. Multipart was the answer. To convert JSON to multipart, Blob was needed.

const writeDiary = function () {
	formData.append("diary",new Blob([JSON.stringify(diary.value)], { type: "application/json" }),);
	store.writeDiary(formData);
};

The key is "diary" and the value is multipart converted from json. The type:~ is telling the Blob that the format of value going to changed is json.

BE

Getting the parameters(Object and file)
It was easy when I tested getting only file. But...getting two parameters was not easy.

	@PostMapping(value="", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
	public ResponseEntity<Diary> writeDiary(
			@RequestPart("diary") Diary diary,
			@RequestPart( required = false) @RequestParam(value="img", required = false) MultipartFile img) {

At first, I tried to send the data as JSON, but I failed. My friend told me sending them as a multipart data would be easier than JSON, I change the format to multipart/form-data.

Setting a path
I was confused how to set the path. -> I wrote it from the root path.

Path baseDirectory = Paths.get([path fromt the root]);

Making a new directory
I wanted to save pictures in the folder named by userId. After that, I saved the file.

String fileName = img.getOriginalFilename();
String saveFileName = uuidFileName(fileName);
Path newDirectory = baseDirectory.resolve(userId);
try {
	Files.createDirectories(newDirectory);
    // Creating the target path within the new directory
    Path targetPath = newDirectory.resolve(saveFileName).normalize();
    // Transfer the file to the target path
    img.transferTo(targetPath.toFile());
    diary.setImg(saveFileName);
 	dService.writeDiary(userId, diary);
} catch (Exception e) {
System.out.println(e.getMessage());
}

0개의 댓글