Какую версию Node вы используете? Если имеется async / await, это очищает кучу.
const moveCsv = (file, dest) => {
return new Promise((resolve, reject) => {
//third
file.mv(dest, function (err) {
if (err) reject(err);
resolve();
});
})
}
app.post('/', async(req, res) => {
try {
var filename = `outputs/${Date.now()}_output.json`;
const {
trainInput,
trainOutput,
testInput
} = req.files;
const prefix = `inputs/${req.body.caseName}`;
await moveCsv(trainInput, `${prefix}/train_input.csv`);
await moveCsv(trainOutput, `${prefix}/train_output.csv`);
await moveCsv(testInput, `${prefix}/test_input.csv`);
res.send('success');
} catch(err) {
res.status(500).send(err);
}
});
Я также предполагаю, что ваши trainInput
, trainOutput
, testOutput
не все должны были быть req.files.trainInput
.
Просто будьте осторожны, поскольку синхронный характер вызовов await
является блокировкой потоков. Если эта функция записи занимает много времени, вы также можете посмотреть, как эти вызовы попадают в рабочий поток. Не имеет значения, будут ли ваши запросы к этой конечной точке сервера быстрыми и частыми.
Я тоже сталкивался с этим и так и не нашел отличного решения. В итоге я сопоставил свой сервлет на один уровень выше в иерархии URL:
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
И теперь все в базовом контексте (и в вашем каталоге / res) может обслуживаться вашим контейнером.
Я бы порекомендовал попробовать использовать фильтр вместо сервлета по умолчанию, когда это возможно.
Другие две возможности:
Напишите FileServlet самостоятельно. Вы найдете множество примеров, он должен просто открыть файл по URL-адресу и записать его содержимое в выходной поток. Затем используйте его для обслуживания запроса статического файла.
Создайте экземпляр класса FileServlet, используемого Google App Engine, и вызовите службу (запрос, ответ) на этом FileServlet, когда вам нужно обслужить статический файл по заданному URL-адресу.
Вы может отобразить / res / * на YourFileServlet или что-то еще, чтобы исключить его из обработки DispatcherServlets, или вызвать его непосредственно из DispatcherServlet.
И я должен спросить, что в документации Spring говорится об этом конфликте? Я никогда им не пользовался.
Я должен спросить, что в документации Spring говорится об этом столкновении? Я никогда им не пользовался. Я должен спросить, что в документации Spring говорится об этом столкновении? Я никогда им не пользовался.Если вы используете Tomcat, вы можете сопоставить ресурсы сервлету по умолчанию:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
и получить доступ к своим ресурсам с помощью url http: // {context path} / static / res / ...
Также работает с Jetty, но не уверен в других контейнерах сервлетов.
«Статические» файлы в App Engine не доступны напрямую из вашего приложения. Вам нужно либо загрузить их дважды, либо обслуживать статические файлы самостоятельно, а не использовать статический обработчик.
Причина коллизии, по-видимому, в том, что по умолчанию корень контекста "/ ", должен обрабатываться org.apache.catalina.servlets.DefaultServlet. Этот сервлет предназначен для обработки запросов на статические ресурсы.
Если вы решите убрать его с пути с помощью собственного сервлета с целью обработки динамических запросов, этот сервлет верхнего уровня должен также выполнять любые задачи, выполняемые с помощью исходный обработчик "DefaultServlet" catalina.
Если вы прочитали документацию tomcat, они упоминают, что True Apache (httpd) лучше, чем Apache Tomcat для обработки статического контента, поскольку он специально создан для этого. Я предполагаю, что Tomcat по умолчанию использует org.apache.catalina.servlets.DefaultServlet для обработки статических запросов. Поскольку все это завернуто в JVM, а Tomcat предназначен как контейнер сервлета / JSP, они, вероятно, не писали этот класс как супероптимизированный обработчик статического содержимого. Это здесь. Он выполняет свою работу. Достаточно хорошо.
Но это то, что обрабатывает статический контент и находится в "/". Итак, если вы поместите туда что-нибудь еще, и эта штука не обрабатывает статические запросы, WHOOPS, туда уйдут ваши статические ресурсы.
Я много и мало искал один и тот же ответ, и везде получаю ответ: «Если вы этого не хотите,
Что вы делаете, так это добавляете приветственный файл в свой web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
, а затем добавляете его в свои сопоставления сервлетов, чтобы, когда кто-то заходит в корень вашего приложения, они отправлялись в index.html внутри, а затем отображение будет внутренне отправлять их сервлету, которому вы сопоставляете его
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
. Конечный результат: вы посещаете / Application, но вам предоставляется сервлет / Application / MainActions, не прерывая никаких других корневых запросов.
Поняли? Таким образом, ваше приложение по-прежнему находится на дополнительном URL-адресе, но автоматически отображается, когда пользователь переходит в корень вашего сайта. Это позволяет вам, чтобы /images/bob.img все еще находился в обычном месте, но '/' - это ваше приложение.
Сопоставьте сервлет контроллера с более конкретным URL-шаблоном
, например /pages/*
, поместите статическое содержимое в определенную папку, например /static
и создайте Filter
, прослушивающий /*
, который прозрачно продолжает цепочку для любого статического контента и отправляет запросы сервлету контроллера для другого контента.
В двух словах:
<filter>
<filter-name>filter</filter-name>
<filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
со следующим в фильтре doFilter()
:
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/static")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/pages" + path).forward(request, response);
}
Нет, это не приводит к /pages
в адресной строке браузера. Он полностью прозрачен. При необходимости вы можете сделать "/static"
и/или "/pages"
init-param
фильтра.
Добавьте папки, которые не должны запускать обработку сервлета, в раздел
вашего файла appengine-web.xml.
Я только что сделал это, и, похоже, все начинает работать нормально. Вот моя структура:
/
/pages/<.jsp files>
/css
Я добавил "/pages/**" и "/css/**" в < static-files>
, и теперь я могу перенаправить файл .jsp из сервлета doGet, не вызывая бесконечного цикла.