Загрузить файл Excel из React в серверную часть C# ASP.NET Core

Я пытаюсь загрузить файл из интерфейса реакции на серверную часть C#. Я использую зону перетаскивания, чтобы получить файл, а затем я вызываю помощник api для публикации файла, но я получаю разные ошибки, когда пробую разные вещи. Я не уверен, какими должны быть заголовки и что мне следует отправлять, но получаю две разные ошибки. Если я не установил тип содержимого, я получаю ошибку 415 (неподдерживаемый тип носителя). Если я укажу тип содержимого как multipart / form-data, я получу внутреннюю ошибку сервера 500. Я получаю ту же ошибку, когда тип содержимого - application / json. URL вставлен, и я уверен, что он правильный. Я не уверен, следует ли добавлять файл как файл [0] [0], как я это сделал, или как файл [0], поскольку это массив, но я считаю, что он должен быть первым. Любые предложения приветствуются :) Вот мой вспомогательный код сообщения api:

export const uploadAdminFile = (file, path, method = 'POST', resource = 
config.defaultResource) => {
const url = createUrl(resource, path);

const data = new FormData();


data.append('file', file[0][0]);
data.append('filename', file[0][0].name);

const request = accessToken =>
fetch(
  url,
  {
    method,
    mode: 'cors',
    withCredentials: true,
    processData: false,
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json', //'multipart/form-data',
      Authorization: `Bearer ${accessToken}`,
    },
    body: data,
  })
  .then(res => res.json())
  .then(success => console.info('API HELPER: file upload success: ', success)
    .catch(err => console.info('API HELPER: error during file upload: ', err)));


return sendRequest(request, resource);

};

«Я получаю внутреннюю ошибку сервера 500.» ... и вы исследовали причину этой ошибки? Это означает, что серверный код каким-то образом сломался. Вам необходимо отладить код сервера, изучить журналы и т. д., Чтобы выяснить, в чем заключалась фактическая ошибка.

ADyson 04.09.2018 11:11

Спасибо, я это понимаю. У меня нет доступа, чтобы сделать это в данный момент, поэтому я спрашиваю, может ли кто-нибудь помочь мне проверить / подтвердить, подтвердить или опровергнуть, что то, что я делаю, «правильно» / должно ли это работать на интерфейсе или есть что-то Я явно ошибаюсь

cbutler 04.09.2018 11:19

если вы пытаетесь загрузить файл, то, конечно, тип содержимого не будет JSON.

ADyson 04.09.2018 11:21

Однако более серьезная проблема, по-видимому, заключается в том, что свойство init в функции выборки не ожидает большинства имен свойств, которые вы там использовали. См. stackoverflow.com/questions/52162745/…. Вы не путаете его с jQuery $ .ajax (api.jquery.com/jquery.ajax) - для меня они похожи на параметры стиля jQuery. Также method должен быть method: "POST" или что-то в этом роде. Само по себе значение без имени бесполезно.

ADyson 04.09.2018 11:22

Они просто используют значения по умолчанию, поэтому мне не нужно их явно отправлять. А с синтаксисом ES ^ вы можете сократить key: value до одного значения, если имена совпадают, так что это то же самое, что и method: method,

cbutler 04.09.2018 11:32

Вы не используете значения по умолчанию для processData или withCredentials (хотя это не является прямым параметром root в любом случае, поэтому это неправильно, найдите его) или метода (параметры стиля jquery), ни для режима (параметр стиля выборки). Вы включаете в него довольно много нестандартных настроек, но вы смешиваете и сопоставляете параметры из двух разных библиотек, поэтому некоторые просто не распознаются функцией выборки и не будут применяться к сгенерированному HTTP-запросу. Решите, какую библиотеку вы хотите использовать, а затем правильно установите необходимые параметры в соответствии с соответствующей документацией.

ADyson 04.09.2018 11:36

Если вы не уверены, какие параметры установить, проконсультируйтесь с разработчиками API. Если у них нет явной документации, они, по крайней мере, должны быть в состоянии рассказать вам, как они ожидают структурирования HTTP-запроса, а затем вы сможете решить, какие параметры вызовут создание соответствующего запроса.

ADyson 04.09.2018 11:36

Какая часть кода - это jQuery?

cbutler 04.09.2018 11:43

Буквально нет jquery синтаксис. Я говорю, что "method", "withCredentials: true" и "processData: false" не являются допустимыми параметрами для метода fetch(), что ясно видно из документации. Однако по совпадению они (почти, в случае withCredentials) являются допустимыми параметрами для метода jQuery $ .ajax (), который также создает HTTP-запросы. Поэтому я предположил, что вы каким-то образом запутались между двумя функциями (fetch () и $ .ajax ()). Вы прочитали две ссылки, которые я вам дал? Откуда у вас возникла идея установить эти значения в функции fetch ()?

ADyson 04.09.2018 11:47

Я тоже прошу прощения - только что понял в моем предыдущем комментарии, я связался с вашим собственным вопросом, когда на самом деле я намеревался связать вас с документами fetch (): developer.mozilla.org/en-US/docs/Web/API/…

ADyson 04.09.2018 11:48

И моя общая точка зрения заключается в том, что тот факт, что вы предоставили параметры, которые на самом деле не работают, может способствовать вашей проблеме, если вы предполагаете, что они повлияют на способ создания HTTP-запроса.

ADyson 04.09.2018 11:50

На самом деле, извините, «метод» допустим в fetch (), но другие, о которых я упоминал, нет. Эта ссылка может оказаться вам полезной: stackoverflow.com/questions/36067767/…. Конечно, как я уже упоминал, вам также необходимо согласовать то, что вы делаете, с требованиями API.

ADyson 04.09.2018 11:59

Спасибо. Я видел этот пост. Сейчас я читаю документы, чтобы убедиться, что что-то из того, что я сделал, недействительно. Да, там есть код для тестирования и т. д., Но из того, что я вижу, я не использую никаких опций, которые недействительны для выборки. withCredentials действительно работает. Я не использую processData (это было то, что я пробовал из других ответов о переполнении стека.

cbutler 04.09.2018 12:10

И да, я видел другой ответ, который вы упомянули

cbutler 04.09.2018 12:10

если вы что-то не используете, удалите это. Какой вопрос предложил использовать ?? И для fetch () не задокументирована опция withCredentials. Вы уверены, что это имеет какой-то эффект? Не должно. Однако, если вы внимательно посмотрите на спецификацию fetch (), есть опция credentials. Однако он не принимает истинные или ложные значения. См. Также stackoverflow.com/questions/40543372/…. Я действительно не понимаю, почему вы продолжаете пробовать значения, которых нет в спецификации, только потому, что вы видели их в случайном вопросе SO.

ADyson 04.09.2018 12:13

Я попробовал все ваши предложения и удалил то, что вы определили. Я просто не обновлял здесь пример кода. Сейчас я думаю, что серверная часть может ожидать файловый поток, и мне нужно будет скрыть excel в json.

cbutler 04.09.2018 12:31

файловый поток - это не JSON. Отправка его в двоичном формате с использованием многостраничного кодирования ближе всего к «потоку» (что вы не можете сделать, используя HTTP таким образом). JSON - это текст. Если вы хотите отправить его в объекте JSON, вам придется закодировать его с помощью base64. Но вам действительно нужно проверить, что API на самом деле ожидает, а не гадать. Найдите его документацию или проконсультируйтесь с соответствующими людьми, которые его поддерживают.

ADyson 04.09.2018 12:41

Думаю, это часть проблемы: ссылка на сайт. Конечная точка ожидает Content-Type: multipart / form-data, однако граница все портит, но мне нужно иметь возможность отправлять accessToken в заголовке. Может быть, мне стоит попробовать другую библиотеку HTTP-запросов, например, axios, Request или superagent.

cbutler 04.09.2018 17:14

граница находится в теле запроса, токен доступа находится в заголовке. Я не понимаю, как они будут противоречить друг другу и насколько это действительно актуально. Вполне возможно отправлять заголовки с помощью составного запроса. Возможно, вам стоит заглянуть в инструменты вашего браузера, чтобы увидеть, как на самом деле выглядит окончательный запрос. Что, если вы просто полностью опустите заголовок contenttype?

ADyson 04.09.2018 17:38

Взгляните на ссылку, которую я опубликовал ... если вы опустите Content-Type, браузер добавит его обратно, а также добавит границу. Прочтите статью, и вы поймете, почему это важно.

cbutler 04.09.2018 20:11

Я понимаю, почему важна граница, но она не имеет ничего общего с заголовком авторизации. Я сделал небольшую демонстрацию здесь. jsfiddle.net/316txzhm/8 Это не идентично вашему коду, но есть самое необходимое с точки зрения того, как делается запрос. Выберите образец файла для загрузки и нажмите кнопку, а затем просмотрите свой запрос. Обратите внимание, что код не устанавливает заголовок типа содержимого, но он снова добавляется правильно с границей. Обратите внимание, что заголовок auth в порядке. Я также записал HTTP-запрос, сгенерированный браузером при его запуске (в Chrome): imgur.com/a/PntHs4L

ADyson 05.09.2018 11:32

AFAIK, это в основном правильный подход к загрузке как файла, так и его имени в отдельные поля в виде запроса, состоящего из нескольких частей. Ожидает ли ваша конечная точка чего-то еще? Граница необходима для того, чтобы конечная точка знала, где заканчиваются данные файла и начинаются данные имени файла. Если он не может с этим справиться, я не могу понять, как он сможет правильно читать требуемые данные. Кстати, вам действительно не нужно отправлять имя файла отдельно - обратите внимание, что запрос все равно включает его вместе с данными файла.

ADyson 05.09.2018 11:33
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
22
1 710
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Спасибо за помощь и предложения, оказалось, что это проблема с серверной частью, но, тем не менее, я многому научился в процессе. Я опубликую здесь свой рабочий код на тот случай, если кто-нибудь столкнется с этим и сочтет его полезным.

export const uploadAdminFile = (file, path, resource=config.defaultResource) => {
  const url = createUrl(resource, path);
  const formData = new FormData();

  formData.append('file', file[0][0]);
  formData.append('filename', file[0][0].name);

  const request = accessToken =>
    fetch(url,
    {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        Authorization: `Bearer ${accessToken}`,
    },
    body: formData,
  });

  return sendRequest(request, resource);
};

Как уже упоминалось, имя файла не нужно отправлять отдельно и не указывать счетчик. Я индексирую файл таким образом, потому что я получаю его из dropzone в виде массива, и мне нужен только один файл (первый в массиве). Я надеюсь, что это поможет кому-то еще, и вот ссылка на mdn получить документы (хорошая информация) и хорошая статья по использованию fetch и formData.

Другие вопросы по теме