【问题标题】:Images uploaded with node corrupted上传的图像节点损坏
【发布时间】:2020-08-08 21:56:29
【问题描述】:

我通过 Next.js API 路由上传的图像已损坏。我正在使用强大的。

我通过这些函数从我的 React 组件提交一个表单:

    const fileUpload = async (file: File) => {
        const url = '/api/image'
        const formData = new FormData()
        formData.append('file', file)
        const config = {
            headers: {
                'content-type': 'multipart/form-data',
            },
        }
        const response = await axios.post(url, formData, config)
        const { data } = response
        return data
    }

    const handleSubmit = async (event: React.SyntheticEvent) => {
        const url = '/api/post'
        if (files) {
                        // ignore 
            fileUpload(files[0]).then((response) =>
                console.log('submit response', response)
            )
        }
        event.preventDefault()
    }

Next 中的 API 路由如下所示:

import formidable from 'formidable'
const fs = require('fs')
const { BlobServiceClient } = require('@azure/storage-blob')

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
}

const AZURE_STORAGE_CONNECTION_STRING =
    process.env.AZURE_STORAGE_CONNECTION_STRING

export const config = {
    api: {
        bodyParser: false,
    },
}

const getBlobName = (originalName) => {
    const identifier = Math.random().toString().replace(/0\./, '')
    return `${identifier}-${originalName}`
}

export default async (req, res) => {
    const form = new formidable.IncomingForm()
    form.keepExtensions = true
    form.uploadDir = './public/static/uploads'

    form.parse(req, async (err, fields, files) => {
        if (err) {
            return
        }
        return res.json({ fields, files })
    })

    form.on('file', async (name, file) => {
        const blobServiceClient = await BlobServiceClient.fromConnectionString(
            AZURE_STORAGE_CONNECTION_STRING
        )
        const containerClient = await blobServiceClient.getContainerClient(
            'images'
        )
        const buff = fs.readFileSync(file.path)
        const data = buff.toString('base64')

        const blobName = getBlobName(file.name)
        const blockBlobClient = containerClient.getBlockBlobClient(blobName)

        blockBlobClient.upload(data, data.length)
    })
}

本地存储的图像已损坏,看起来像是调到死频道的电视。我显然没有正确编码它 - 但不确定它是我的 ContentType 还是字符串编码?

【问题讨论】:

    标签: node.js reactjs typescript azure-blob-storage next.js


    【解决方案1】:

    我相信问题来了,因为您正在将数据转换为 base64 编码的字符串:

    const data = buff.toString('base64')
    

    考虑到您已经将上传的文件保存在服务器的某个位置(这是由formidable 包完成的),请尝试以下操作:

        const blobName = getBlobName(file.name)
        const blockBlobClient = containerClient.getBlockBlobClient(blobName)
        blockBlobClient.uploadFile(file.path)
    

    uploadFile() 方法参考:https://docs.microsoft.com/en-gb/javascript/api/@azure/storage-blob/blockblobclient?view=azure-node-latest#uploadfile-string--blockblobparalleluploadoptions-

    更新

    请尝试此代码。我刚刚尝试了这段代码,并且能够成功上传文件。当我下载文件时,它没有损坏。

      form.on('file', async (name, file) => {
        const blobServiceClient = await BlobServiceClient.fromConnectionString(AZURE_STORAGE_CONNECTION_STRING);
        const containerClient = await blobServiceClient.getContainerClient('images');
        const blobName = file.name;
        const contentType = file.type;
        const filePath = file.path;
        const blockBlobClient = containerClient.getBlockBlobClient(blobName);
        const uploadBlobResponse = await blockBlobClient.uploadFile(file.path);
      });
    

    更新 #2

    这是我使用的完整代码:

    <form id="form1" method="post" action="/upload" enctype="multipart/form-data">
      <input name="file" type="file" id="file1" accept="image/*"/>
      <input type="button" id="button1" value="Upload" />
    </form>
    
    
    <script src="https://code.jquery.com/jquery-1.12.4.js" integrity="sha256-Qw82+bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU=" crossorigin="anonymous"></script>
    
    <script>
      $(document).on('ready', function() {
    
      });
      $('#button1').on('click', function(e) {
        data = new FormData();
        console.log($('#file1')[0].files[0]);
        data.append('file', $('#file1')[0].files[0]);
        console.log(data);
        $.ajax({
                url: '/upload',
                data: data,
                processData: false,
                contentType: false,
                type: 'POST',
                success: function ( data ) {
                    alert( data );
                }
            });
        e.preventDefault();
        e.stopPropagation();
      });
    </script>
    

    var express = require('express'),
        path = require('path'),
        fs = require('fs'),
        formidable = require('formidable');
    const { BlobServiceClient } = require('@azure/storage-blob');
    
    var app = express();
    
    app.set('port', (process.env.PORT || 5000));
    
    // Tell express to serve static files from the following directories
    app.use(express.static('public'));
    app.use('/uploads', express.static('uploads'));
    
    app.listen(app.get('port'), function() {
        console.log('Express started at port ' + app.get('port'));
    });
    
    app.get('/', function (req, res) {
        res.sendFile(path.join(__dirname, 'index.html'));
    });
    
    
    app.post('/upload', function(req, res) {
      const connectionString = 'DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key;EndpointSuffix=core.windows.net;';
      const container = 'container-name';
    
      let form = new formidable.IncomingForm();
      form.keepExtensions = true;
      form.uploadDir = './public/static/uploads';
      form.parse(req, async function (err, fields, files) {
      });
    
      form.on('file', async (name, file) => {
        const blobServiceClient = await BlobServiceClient.fromConnectionString(connectionString);
        const containerClient = await blobServiceClient.getContainerClient(container);
        const blobName = file.name;
        const contentType = file.type;
        const filePath = file.path;
        console.log(file);
        const blockBlobClient = containerClient.getBlockBlobClient(blobName);
        const uploadBlobResponse = await blockBlobClient.uploadFile(file.path);
        console.log(uploadBlobResponse);
      });
    });
    

    【讨论】:

    • 该文件在服务器和 Blob 存储上已损坏 — 除非我误解了响应。
    • 不幸的是对我不起作用。这是它的实际价值:designstream.blob.core.windows.net/images/… — 注意到 contentType 未使用,所以我尝试使用 file.type 作为配置头对象中的“内容类型”。
    • 你能分享一下实际的图片吗?我会尝试并分享完整的代码。
    • 这里是原始图像的链接:dsc.cloud/5578af/davide-cantelli-240809-unsplash.jpg — 该图像在 public/static/uploads 路径的本地仍然损坏。
    • 感谢分享原图。我尝试了它,但仍然无法重现该问题。用我正在使用的完整代码更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2020-04-15
    • 2016-04-14
    • 2016-12-26
    • 2021-03-15
    相关资源
    最近更新 更多