Reputation: 25
I have this part of C# code that works fine with another NodeJS Express app to which source code I don't have access, and I would like to leave this code as is.
string filetoupload = @"D:\testvideo.mp4";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://127.0.0.1:10090" + "/upload?name=" + WebUtility.UrlEncode(Path.GetFileName(filetoupload)));
request.Method = "PUT";
request.ContentType = MimeTypesMap.GetMimeType(Path.GetExtension(filetoupload));
using (FileStream fs = File.OpenRead(filetoupload))
{
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
request.ContentLength = buffer.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Flush();
requestStream.Close();
WebResponse upresponse = request.GetResponse();
Stream updataStream = upresponse.GetResponseStream();
StreamReader upreader = new StreamReader(updataStream);
string upres = upreader.ReadToEnd();
Console.WriteLine("RES: " + upres);
}
Problem is I don't know how to properly read stream data on NodeJS Express end. I have managed to read it and to store file on disk using this code
const express = require('express');
const fs = require('fs');
const app = express();
const port = process.env.PORT || 10090;
app.listen(port, () =>
console.log(`App is listening on port ${port}.`)
);
app.put('/upload', async (req, res) => {
try {
var socket = req.socket;
socket.on('data', function(data) {
fs.appendFile("somevideo.mp4", new Buffer(data), function (err,data) {
if (err) {
res.status(500).send(err);
}
});
});
res.send({
status: true,
message: 'File uploaded'
});
} catch (err) {
res.status(500).send(err);
}
});
But I need to do some more work after file is stored on disk (creating hash code, do some MySQL work, etc.) and then return some text data as response message. Problem for me is how to know when that has happened?
Is there another (right) way to store files uploaded like this?
Upvotes: 0
Views: 1050
Reputation: 2131
These days I've done some similar work. It was uploading multiple images + input data from Laravel (PHP) to Node.js as multipart form data with multer. Honestly I don't know C#, may you will need to change something in your C# code, but I think there's no much work in C# side. Additionally, you can see this thread for simplicity.
IMO this could be useful for you in Node.js part, as this code is not depending from client-side language.
Create Multer's utility somewhere ("utilities/multer.js" in this example):
const multer = require('multer');
const path = require('path');
module.exports = {
fileUpload: function () {
return multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
const filePath = path.join(__dirname, './../uploads');
cb(null, filePath);
},
filename: function (req, file, cb) {
const extension = 'mp4';
const dateField = (new Date().getTime() / 1000 | 0);
const randomField = Math.random().toString(36).substring(2);
const fileName = `${dateField}-${randomField}.${extension}`;
cb(null, fileName);
},
}),
limits: {
fileSize: 1024 * 1024 * 20 // max file size in MB
},
fileFilter: (req, file, cb) => {
let valid = (file.mimetype === 'text/plain');
cb(null, valid);
},
});
}
};
In your routes add the appropriate route ("routes/item.js" in this example):
const { Router } = require('express');
const router = Router();
const itemController = require('./../controllers/item');
const fileUpload = require('./../utilities/multer').fileUpload();
router.put('/upload',
fileUpload.any('files', 10), // uploading files max count
itemController.create);
// other routes ...
module.exports = router;
Now in your controller you can continue coding ("controllers/item.js" in this example):
module.exports = {
create: async (req, res) => {
if (req.files.length === 0) {
return res.status(403).json({
error: "File(s) required!"
});
}
const parsedData = JSON.parse(req.body.data);
// some code block ...
return res.status(201).json({
title: parsedData.title,
description: parsedData.description,
});
},
};
Don't forget to customize this code for your needs. Anyway this was worked for me perfectly.
Also as I'm not sure about C# codes, so I can provide the request info with Postman which I've used:
And this is the default generated C# (RestSharp) code by Postman for appropriate request:
var client = new RestClient("http://localhost:3000/api/v1/item/upload");
client.Timeout = -1;
var request = new RestRequest(Method.PUT);
request.AddHeader("Authorization", "Bearer CUSTOMER_ID_TOKEN");
request.AddFile("files", "/home/user/Downloads/video1.mp4");
request.AddFile("files", "/home/user/Downloads/video2.mp4");
request.AddParameter("title", "This is an awesome product!");
request.AddParameter("description", "This is an awesome product!");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Upvotes: 1