首页 > 解决方案 > 使用 HttpWebRequest 从 C# 上传图像到使用 PUT 方法的 NodeJS Express

问题描述

我有这部分 C# 代码可以与另一个我无权访问的 NodeJS Express 应用程序一起正常工作,我想保留此代码原样。

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);
}

问题是我不知道如何在 NodeJS Express 端正确读取流数据。我已经设法阅读它并使用此代码将文件存储在磁盘上

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);
    }
});

但是在文件存储在磁盘上之后我需要做更多的工作(创建哈希码,做一些 MySQL 工作等),然后返回一些文本数据作为响应消息。对我来说,问题是如何知道那是什么时候发生的?

是否有另一种(正确的)方法来存储像这样上传的文件?

标签: c#node.jsexpressfile-upload

解决方案


这些天我做了一些类似的工作。它使用 multer 将多个图像 + 输入数据从 Laravel (PHP) 上传到 Node.js 作为多部分表单数据。老实说,我不了解 C#,可能您需要更改 C# 代码中的某些内容,但我认为 C# 方面没有太多工作。此外,为简单起见,您可以查看线程。

IMO 这在 Node.js 部分可能对您有用,因为此代码不依赖于客户端语言。

在某处创建 Multer 的实用程序(本例中为“utilities/multer.js”):

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);
            },
        });
    }
};

在您的路线中添加适当的路线(本例中为“routes/item.js”):

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;

现在在您的控制器中,您可以继续编码(本例中为“controllers/item.js”):

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,
        });
    },
};

不要忘记根据您的需要自定义此代码。无论如何,这对我来说非常有用。

另外,由于我不确定 C# 代码,因此我可以使用我使用过的 Postman 提供请求信息:

邮差

这是 Postman 针对适当请求默认生成的 C# (RestSharp) 代码:

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);

推荐阅读