0

I've been following some guides (how to upload image file and display using express nodejs, NodeJS Multer is not working for exmaple) on how to upload an image, but I have had problems getting the image to be uploaded to by backend directory. Here is my code:

Angular Frontend

//html
<input type="file" name="image" (change)="onFileSelected($event)">
<button (click)="uploadImage()">Save Image</button>

//ts
formData = new FormData();

  onFileSelected(event) {
    this.uploadedImage = event.target.files[0]
}

uploadImage() {
    if (this.uploadedImage) {
      this.formData.append('image', this.uploadedImage, this.uploadedImage.name)
      console.log(this.formData.getAll('image')) //confirms file is being uploaded properly
      this.httpService.upload('uploadImage/', this.formData).subscribe((message: any) => {
        console.log(message)
      });
}

//httpService
  upload(url, file) {
    console.log("uploading file")
    return this.http.post(this.baseUrl + url, file);
  }

Node Backend

//index.js
var http = require('http');
var express = require('express');
var cors = require('cors');
var app = express();
var multer = require('multer')
var path = require('path')
var bodyParser = require('body-parser');

app.use(cors());

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, path.resolve(__dirname, '../documents/'));
    },
    filename: (req, file, cb) => {
        console.log(file);
        cb(null, Date.now() + path.extname(file.originalname));
    }
});
const fileFilter = (req, file, cb) => {
    if (file.mimetype == 'image/jpeg' || file.mimetype == 'image/png') {
        cb(null, true);
    } else {
        cb(null, false);
    }
}
const upload = multer({ storage: storage, fileFilter: fileFilter });

app.use(bodyParser.json());

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "http://localhost:4200");
    res.header('Access-Control-Allow-Methods', 'GET,POST,PATCH,PUT,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    next();
})

// other API requests...

app.post('/api/uploadImage/', upload.single('image'), (req, res, next) => {
    console.log(req.file) //returns undefined
    try {
        return res.status(201).json({
            message: 'File uploaded successfully'
        });
    } catch(error) {
        console.error(error);
    }
});

var server = http.createServer(app)

server.listen(5000, function() {
  console.log('Http Server is up and running.');
}

I get the message 'File uploaded successfully' from the backend after the HttpService is finished, but there is no image in my /documents/ directory. From what I can tell, the image should be coming over through the req.file or req.files variable, but returns undefined. What am I doing wrong here?

2
  • Could you update your Node code to be exactly as your local machine, maybe we are missing something in the backend? Commented Oct 23, 2020 at 0:21
  • I'll go ahead and add most of the code from the index.js file. Commented Oct 24, 2020 at 4:08

2 Answers 2

1

The issue is within your Angular application in the input field. Your ngModel is doing nothing because doesn't have the correct syntax, and even so it would only hold a fake path to the image.

There are several ways to get the actual File object from an input field. The simplest one is to use the onChange event. It would be something like this:

<input type="file" name="image" (change)="onChange($event)">

And inside your TS file:

onChange(event: any) {
    this.uploadedImage = event.target.files[0];
}

You will also need to update your upload method inside your service because multer parses a FormData, so you must send your data as a FormData.

const data = new FormData();
data.append('image', this.file, this.file.name);
return this.http.post(this.baseUrl + url, data);

Note: You are getting "File uploaded successfully" from the backend, because multer does not throw an error even if there is no data to process so your upload endpoint will always return the success code 201 even if no file was actually uploaded.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the response. I had some of this commented out as I've tried this before, but I will give it another shot. I'll update the main post --- I am getting the same result, no errors from multer, but no file upload. It seems to me that multer can't find the 'image' object. Do you know where that comes in from the req object? Req.body, req.file, req.files?
It looks like it is supposed to come over via req.body and req.files. However, it needs to be encoded with type multipart/form-data. I did exactly that and it still doesn't work. - Source: stackoverflow.com/questions/44861517/…
Are you initializing the FormData correctly? I don't see that part in your updated answer.
It's simply formData = new FormData();. I've tried it inside the uploadImage() function too but neither works.
Thanks for your help, you pushed me in the right direction. I just needed to encode the formData properly.
0

I discovered that the issue was related to the FormData's inability to transmit to the backend, and needed to be encoded correctly. Following an explanation here, I changed up the HTML to look like this:

<form enctype="multipart/form-data" (ngSubmit)="uploadImage()">
   <input type="file" name="image" (change)="onFileSelected($event)">
   <button>Save Image</button>
</form>

The backend received the request through req.body and the file was successfully uploaded.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.