Как переписать угловой ng-file-upload Upload.upload с помощью JS fetch? - PullRequest
0 голосов
/ 05 мая 2019

Мне нужно загрузить файл на сервер, используя fetch() из собственного приложения реагирования

У меня есть следующий код на Angular, который использует ng-file-upload:

в этом функциональном файле прикреплена переменная FormData

    function addDocumentToMessage(messageId, file) {

        data.filepath = file;
        data.name = file.name;

        return Upload.upload({
                url: BackendUrl + "/messages/" + messageId + "/attachments/",
                file: file,
                data: data
            })
            .then(responseHandler)
            .catch(errorHandler);
    }

Я пытался выполнить следующие действия, используя fetch(), но это не работает должным образом: файл добавлен на сервер, но вложения и другие поля там не сохраняются. Вот код, который я пробовал:

document = { formData, name }

export const addDocumentToMessage = (token, logId, document) => {
    const file = document.formData
    const data = { filepath: file, name: document.name }

    fetch(`${API_URL}/messages/${logId}/attachments/`, {
        method: 'POST',
        headers: { 'Authorization': `token ${token}`, 'Content-Type': 'multipart/form-data', Accept: 'application/json' },
        body: JSON.stringify({ file: file, data: data })
    })
        .then(response => console.log(response.data))
        .catch(error => console.log(error.message))
}

1 Ответ

0 голосов
/ 05 мая 2019

Кажется, что два Content-Types были смешаны здесь:

  • multipart/form-data для отправки двоичного содержимого файла в file
  • application/json для отправки некоторых данных JSON в body

Поскольку HTTP-запросы поддерживают только одно тело, имеющее одну кодировку Content-Type, мы должны объединить все это, чтобы оно было multipart/form-data. В следующем примере используется переменная formData для объединения (двоичных) данных файла с произвольными данными JSON.

export const addDocumentToMessage = (token, logId, document) => {

    // commented these lines since I wanted to be more specific
    // concerning the origin and types of data
    // ---
    // const file = document.formData
    // const data = { filepath: file, name: document.name }

    const fileField = document.querySelector("input[type='file']");
    let formData = new FormData();

    formData.append('file', fileField.files[0]);
    formData.append('name'. fileField.files[0].name);
    formData.append('arbitrary', JSON.stringify({hello: 'world'}));

    fetch(`${API_URL}/messages/${logId}/attachments/`, {
        method: 'POST',
        headers: {
            'Authorization': `token ${token}`,
            'Accept': 'application/json'
            // 'Content-Type': 'multipart/form-data',
        },
        body: formData
    })
        .then(response => console.log(response.data))
        .catch(error => console.log(error.message))
}

В этом случае полезная нагрузка тела HTTP-запроса будет выглядеть следующим образом:

------WebKitFormBoundarypRlCB48zYzqAdHb8
Content-Disposition: form-data; name="file"; filename="some-image-file.png"
Content-Type: image/png

... (binary data) ...
------WebKitFormBoundarypRlCB48zYzqAdHb8
Content-Disposition: form-data; name="name"

some-image-file.png
------WebKitFormBoundarypRlCB48zYzqAdHb8
Content-Disposition: form-data; name="arbitrary"

{"hello":"world"}
------WebKitFormBoundarypRlCB48zYzqAdHb8--

Ссылки:

...