如何使用带有 <script setup> 的 Axios / Vue 将文件上传到 Django REST API 后端
How to upload files with Axios / Vue with <script setup> to Django REST API backend
我在下面设置了 Vue 前端/Django REST API 后端存储库。
我正在努力寻找一种方法将文件发送到 Django 后端。
Django 后端
https://github.com/TraitOtaku/Vue-File-Upload
Vue 前端
https://github.com/TraitOtaku/Django-Rest-API-for-Fileupload
我能够确认我可以使用 Django API 界面上传文件(下图)
Django API interface
并且还使用了 postman 桌面应用程序。
我这里的具体问题是,当用户选择文件时,我不知道如何将文件数据附加到 POST 请求。
在 Vue 存储库中,vue 文件中有一个 App.vue 和表单。
<template>
<div class="container mt-5">
formState:{{ formState }}
<form enctype="multipart/form-data">
<div class="form-group my-2">
<label for="exampleInputEmail1">File Name</label>
<input class="form-control" v-model="formState.name">
</div>
<div class="form-group my-2">
<label class="form-label" for="customFile">Upload Store Documents</label>
<input type="file" class="form-control" id="storeFile"
@change="appendFile(event.target.name, event.target.files)" />
</div>
<button type="submit" class="btn btn-primary" @click.prevent="createStoreDoc">Submit</button>
</form>
<h1>Store Documents</h1>
<div v-if="storeDoc">
<div v-for="doc in storeDoc" :key="doc.id">
<div>
File ID:{{ doc.id }}
</div>
<div>
File Name:{{ doc.name }}
</div>
<div>
File Content:{{ doc.file }}
</div>
<hr>
</div>
</div>
</div>
</template>
<script setup>
import axios from "axios";
import { ref, toRaw, reactive } from "vue";
const formState = reactive({
name: "",
file: null,
});
const apiClient = axios.create({
baseURL: "http://127.0.0.1:8000/api/store-doc/",
withCredentials: false,
headers: {
// Accept: "application/json",
"Content-Type": "application/json",
},
});
const storeDoc = ref(null)
const getStoreDoc = () => {
apiClient.get()
.then((response) => {
storeDoc.value = response.data
// console.log(storeDoc)
})
}
getStoreDoc()
const createStoreDoc = () => {
apiClient.post('', toRaw(formState))
.then((response) => {
console.log("success!" + response.data);
getStoreDoc()
})
.catch((error) => {
console.log(error);
});
}
</script>
我有这个 POST 请求 createStoreDoc(),这会起作用,但还不会将文件附加到请求。
我想用或合成 API 而不是选项 API 来实现这个。
请随意分叉回购协议来回答这个问题。
感谢您阅读并分享您的知识。
这里我会怎么做:
你在 Content-Type
header 中将 application/json
替换为 multipart/form-data
:
const apiClient = axios.create({
baseURL: "http://127.0.0.1:8000/api/store-doc/",
withCredentials: false,
headers: {
// Accept: "application/json",
"Content-Type": "multipart/form-data",
},
});
并创建一个 FormData 实例并将您的数据附加到 createStoreDoc 函数中:
const createStoreDoc = () => {
let formData = new FormData();
formData.append('name', formState.name);
formData.append('file', formState.file, 'filename.docx');
apiClient.post('', formData)
.then((response) => {
console.log("success!" + response.data);
getStoreDoc()
})
.catch((error) => {
console.log(error);
});
}
此时正在提出的请求:
curl 'http://127.0.0.1:8000/api/store-doc/' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDhFZwmF0hYfGZyHU' \
--data-binary $'------WebKitFormBoundaryDhFZwmF0hYfGZyHU\r\nContent-Disposition: form-data; name="name"\r\n\r\ntest\r\n------WebKitFormBoundaryDhFZwmF0hYfGZyHU\r\nContent-Disposition: form-data; name="file"\r\n\r\nnull\r\n------WebKitFormBoundaryDhFZwmF0hYfGZyHU--\r\n' \
--compressed
这里我们在表单数据中看到了文件,但它是空的,因为输入有错误所以我们修复它:
<input type="file" class="form-control" id="storeFile"
@change="appendFile($event.target.name, $event.target.files)" />
然后,由于那个错误,它在 formState 中仍然是 null :
runtime-core.esm-bundler.js?5c40:218 Uncaught TypeError: _ctx.appendFile is not a function
所以我们通过添加 appendFile 函数来修复它:
const formState = reactive({
name: "",
file: null,
filename: null
});
const appendFile = (name, files) => {
formState.filename = name;
formState.file = files[0];
}
作为旁注,我们在状态中添加了文件名,并在 createStoreDoc 函数中使用了它:
formData.append('file', formState.file, formState.filename);
我们收到了请求:
curl 'http://127.0.0.1:8000/api/store-doc/' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary0p7GnwTxmLgGiCHx' \
--data-binary $'------WebKitFormBoundary0p7GnwTxmLgGiCHx\r\nContent-Disposition: form-data; name="name"\r\n\r\ntest\r\n------WebKitFormBoundary0p7GnwTxmLgGiCHx\r\nContent-Disposition: form-data; name="file"; filename="filename.docx"\r\nContent-Type: image/png\r\n\r\n\r\n------WebKitFormBoundary0p7GnwTxmLgGiCHx--\r\n' \
--compressed
文件作为二进制数据上传
我在下面设置了 Vue 前端/Django REST API 后端存储库。 我正在努力寻找一种方法将文件发送到 Django 后端。
Django 后端 https://github.com/TraitOtaku/Vue-File-Upload
Vue 前端 https://github.com/TraitOtaku/Django-Rest-API-for-Fileupload
我能够确认我可以使用 Django API 界面上传文件(下图) Django API interface
并且还使用了 postman 桌面应用程序。
我这里的具体问题是,当用户选择文件时,我不知道如何将文件数据附加到 POST 请求。
在 Vue 存储库中,vue 文件中有一个 App.vue 和表单。
<template>
<div class="container mt-5">
formState:{{ formState }}
<form enctype="multipart/form-data">
<div class="form-group my-2">
<label for="exampleInputEmail1">File Name</label>
<input class="form-control" v-model="formState.name">
</div>
<div class="form-group my-2">
<label class="form-label" for="customFile">Upload Store Documents</label>
<input type="file" class="form-control" id="storeFile"
@change="appendFile(event.target.name, event.target.files)" />
</div>
<button type="submit" class="btn btn-primary" @click.prevent="createStoreDoc">Submit</button>
</form>
<h1>Store Documents</h1>
<div v-if="storeDoc">
<div v-for="doc in storeDoc" :key="doc.id">
<div>
File ID:{{ doc.id }}
</div>
<div>
File Name:{{ doc.name }}
</div>
<div>
File Content:{{ doc.file }}
</div>
<hr>
</div>
</div>
</div>
</template>
<script setup>
import axios from "axios";
import { ref, toRaw, reactive } from "vue";
const formState = reactive({
name: "",
file: null,
});
const apiClient = axios.create({
baseURL: "http://127.0.0.1:8000/api/store-doc/",
withCredentials: false,
headers: {
// Accept: "application/json",
"Content-Type": "application/json",
},
});
const storeDoc = ref(null)
const getStoreDoc = () => {
apiClient.get()
.then((response) => {
storeDoc.value = response.data
// console.log(storeDoc)
})
}
getStoreDoc()
const createStoreDoc = () => {
apiClient.post('', toRaw(formState))
.then((response) => {
console.log("success!" + response.data);
getStoreDoc()
})
.catch((error) => {
console.log(error);
});
}
</script>
我有这个 POST 请求 createStoreDoc(),这会起作用,但还不会将文件附加到请求。
我想用或合成 API 而不是选项 API 来实现这个。 请随意分叉回购协议来回答这个问题。
感谢您阅读并分享您的知识。
这里我会怎么做:
你在 Content-Type
header 中将 application/json
替换为 multipart/form-data
:
const apiClient = axios.create({
baseURL: "http://127.0.0.1:8000/api/store-doc/",
withCredentials: false,
headers: {
// Accept: "application/json",
"Content-Type": "multipart/form-data",
},
});
并创建一个 FormData 实例并将您的数据附加到 createStoreDoc 函数中:
const createStoreDoc = () => {
let formData = new FormData();
formData.append('name', formState.name);
formData.append('file', formState.file, 'filename.docx');
apiClient.post('', formData)
.then((response) => {
console.log("success!" + response.data);
getStoreDoc()
})
.catch((error) => {
console.log(error);
});
}
此时正在提出的请求:
curl 'http://127.0.0.1:8000/api/store-doc/' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDhFZwmF0hYfGZyHU' \
--data-binary $'------WebKitFormBoundaryDhFZwmF0hYfGZyHU\r\nContent-Disposition: form-data; name="name"\r\n\r\ntest\r\n------WebKitFormBoundaryDhFZwmF0hYfGZyHU\r\nContent-Disposition: form-data; name="file"\r\n\r\nnull\r\n------WebKitFormBoundaryDhFZwmF0hYfGZyHU--\r\n' \
--compressed
这里我们在表单数据中看到了文件,但它是空的,因为输入有错误所以我们修复它:
<input type="file" class="form-control" id="storeFile"
@change="appendFile($event.target.name, $event.target.files)" />
然后,由于那个错误,它在 formState 中仍然是 null :
runtime-core.esm-bundler.js?5c40:218 Uncaught TypeError: _ctx.appendFile is not a function
所以我们通过添加 appendFile 函数来修复它:
const formState = reactive({
name: "",
file: null,
filename: null
});
const appendFile = (name, files) => {
formState.filename = name;
formState.file = files[0];
}
作为旁注,我们在状态中添加了文件名,并在 createStoreDoc 函数中使用了它:
formData.append('file', formState.file, formState.filename);
我们收到了请求:
curl 'http://127.0.0.1:8000/api/store-doc/' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary0p7GnwTxmLgGiCHx' \
--data-binary $'------WebKitFormBoundary0p7GnwTxmLgGiCHx\r\nContent-Disposition: form-data; name="name"\r\n\r\ntest\r\n------WebKitFormBoundary0p7GnwTxmLgGiCHx\r\nContent-Disposition: form-data; name="file"; filename="filename.docx"\r\nContent-Type: image/png\r\n\r\n\r\n------WebKitFormBoundary0p7GnwTxmLgGiCHx--\r\n' \
--compressed
文件作为二进制数据上传