【问题标题】:POST image to django rest API always returns 'No file was submitted'将图像发布到 django rest API 始终返回“未提交文件”
【发布时间】:2021-04-11 09:47:34
【问题描述】:

我现在正努力让这个工作好几天-.-

使用简单的 NodeJS express 服务器,我想通过 Post 请求将图像上传到 Django 实例,但我不知道如何准备请求并嵌入文件。

稍后我想发布从客户端的画布创建的图像, 但为了测试,我试图从 nodeJS 服务器上传现有图像。

app.post('/images', function(req, res) {

    const filename = "Download.png"; // existing local file on server

    // using formData to create a multipart/form-data content-type
    let formData = new FormData();
    
    let buffer = fs.readFileSync(filename);
    formData.append("data", buffer); // appending the file a buffer, alternatively could read as utf-8 string and append as text
    
    formData.append('name', 'var name here'); // someone told me, I need to specify a name
    
    const config = {
        headers: { 'content-type': 'multipart/form-data' }
    }

    axios.post("http://django:8000/images/", formData, config)
    .then(response => {
        console.log("success!"); // never happens :(
    })
    .catch(error => {
        console.log(error.response.data); // no file was submitted
    });
});

我做错了什么还是我错过了什么?

编辑

我刚刚在 npm 表单数据页面的最底部 (npmjs.com/package/form-data) 上找到了一个不错的 sn-p 和其他方法:


const filename = "Download.png"; // existing local file on server

let formData = new FormData();

let stream = fs.createReadStream(filename);
formData.append('data', stream)

let formHeaders = formData.getHeaders()

axios.post('http://django:8000/images/', formData, {
    headers: {
        ...formHeaders,
    },
})
.then(response => {
    console.log("success!"); // never happens :(
})
.catch(error => {
    console.log(error.response.data); // no file was submitted
});

遗憾的是,这并没有改变任何东西 :( 我仍然只收到错误请求:没有提交文件

我并没有太多的 Django 代码,只是一个使用带有图像模型的 rest_framework 的基本设置:

class Image(models.Model):
    data = models.ImageField(upload_to='images/')

    def __str__(self):
        return "Image Resource"

它们也在 admin.py 中注册,
序列化器:

from .models import Image


class ImageSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Image
        fields = ('id', 'data')

使用自动 URL 路由。

我编写了一个简单的测试脚本并将相同的图像放在 django 服务器上,以验证图像上传是否有效,并且确实有效:

import requests

url = "http://127.0.0.1:8000/images/"

file = {'data': open('Download.png', 'rb')}
response = requests.post(url, files=file)


print(response.status_code) # 201

【问题讨论】:

  • 我认为错误可能出在后端以及表单数据的处理方式。如果你也可以分享后端代码。

标签: javascript node.js django axios


【解决方案1】:

在您的 node.js express 服务器中,不要将图像添加到表单数据中,而是尝试直接在 API 帖子中发送流。

const filename = "Download.png"; // existing local file on server

//let formData = new FormData();

let stream = fs.createReadStream(filename);
//formData.append('data', stream)

let formHeaders = formData.getHeaders()

axios.post('http://django:8000/images/', stream, {
    headers: {
        ...formHeaders,
    },
})
.then(response => {
    console.log("success!"); // never happens :(
})
.catch(error => {
    console.log(error.response.data); // no file was submitted
});

【讨论】:

  • 如果我根本不使用 formData(以及 formHeaders,如果不注释掉会抛出错误),我会收到同样的错误。这有点奇怪,因为我记得我读过这需要能够为多部分数据设置边界,这是我在link 之前收到的错误
【解决方案2】:

我仍然无法在 axios 上使用它,所以我尝试了另一个包以将文件作为发布请求发送,即 unirest,它对我来说是开箱即用的。

而且它更小,需要更少的代码,并且可以满足我的所有需求:

const filename = "Download.png"; // existing local file on server

unirest
    .post(url)
    .attach('data', filename) // reads directly from local file
    //.attach('data', fs.createReadStream(filename)) // creates a read stream
    //.attach('data', fs.readFileSync(filename)) // 400 - The submitted data was not a file. Check the encoding type on the form. -> maybe check encoding?
    .then(function (response) {
        console.log(response.body) // 201
    })
    .catch((error) => console.log(error.response.data));

如果我将来有空闲时间,我可能会调查我的 axios 实现有什么问题,或者有人知道解决方案,请告诉我:D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-28
    • 1970-01-01
    • 2016-05-30
    • 2018-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多