java - JIRA - 从附加管理页面上传文件到服务器
问题描述
我正在为需要上传文件的 JIRA 开发一个插件。该文件包含定义插件行为的 JSON 格式的规则。我在管理页面中定义了一个 multipart-config servlet 和一个 multipart/form-data 表单。但是我无法在 servlet 端使用 getPart 方法检索任何部分,它似乎到达“空”,就像没有定义任何形式一样。
这些是我的一些代码:
上传规则模板(vm):
...
<form id="upload-rules" class="aui" method="POST" enctype="multipart/form-data">
<input type="hidden" id="uploading" name="uploading" value="y">
<input type="hidden" id="test" name="test" value="y">
<div class="field-group">
<label for="file">Rules config file<span class="aui-icon icon-required">(required)</span></label>
<input type="file" id="file" name="file" class="file">
</div>
<div class="field-group">
<input type="submit" value="Upload" class="button" name="upload" id="upload">
<a href="$baseURL/plugins/servlet/upm">Cancel</a>
</div>
</form>
...
规则Servlet.java
...
@Named("RulesServlet")
@MultipartConfig
public class RulesServlet extends HttpServlet
{
...
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
LOG.debug("doGet method called.");
//Only admin users are admitted
if (!isAdminUser(request)) {
redirectToLogin(request, response);
return;
}
AutoEscalateConfig autoEscalateConfig = null;
...stuff for getting configs...
if ("preupload".equals(request.getParameter("op"))) {
Map<String, Object> context = getContextWithCommonParams(autoEscalateConfig);
// Render the template with the issue inside the context
response.setContentType(CONTENT_TYPE);
renderer.render(UPLOAD_TEMPLATE, context, response.getWriter());
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
LOG.debug("doPost method called.");
//Only admin users are admitted
if (!isAdminUser(request)) {
redirectToLogin(request, response);
return;
}
try {
LOG.debug("Updating rules...");
LOG.debug("Request content type: " + request.getContentType());
LOG.debug("Request parameterMap size: " + request.getParameterMap().size());
LOG.debug("Request parts size: " + request.getParts().size());
Part filePart = request.getPart("file"); // Retrieves <input type="file" name="file">
String fileName = Paths.get(getSubmittedFileName(filePart)).getFileName().toString(); // MSIE fix.
InputStream fileContent = filePart.getInputStream();
...stuff to get rules from file...
response.setContentType(CONTENT_TYPE);
renderer.render(UPLOAD_TEMPLATE, context, response.getWriter());
} catch (Exception e) {
LOG.error("Error creating escalate rules.", e);
throw new ServletException(e);
}
}
private static String getSubmittedFileName(Part part) {
for (String cd : part.getHeader("content-disposition").split(";")) {
if (cd.trim().startsWith("filename")) {
String fileName = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", "");
return fileName.substring(fileName.lastIndexOf('/') + 1).substring(fileName.lastIndexOf('\\') + 1); // MSIE fix.
}
}
return null;
}
}
...
atlassian-plugin.xml
...
<servlet key="mim-autoescalate-upload-rules-servlet" i18n-name-key="mim-autoescalate-rules-upload-servlet.name"
class="cat.palma.jira.escalate.ui.RulesServlet" name="MIM Autoescalate Plugin Upload Rules Servlet">
<description key="mim-autoescalate-rules-upload-servlet.description">The rules upload servlet to populate the MIM Autoescalate Plugin rule table</description>
<url-pattern>/mimautoescalateplugin/rules</url-pattern>
</servlet>
...
<web-item key="mim-autoescalate-link-upload-rules" i18n-name-key="mim-autoescalate-link-upload-rules.name"
name="MIM Autoescalate Plugin Setup Rules Link" section="admin_plugins_menu/mim-autoescalate-section" weight="1010">
<description key="mim-autoescalate-link-upload-rules.description">The Setup Page Link for escalate rules of MIM Autoescalate Plugin</description>
<label key="mim-autoescalate-link-upload-rules.label"></label>
<link linkId="mim-autoescalate-link-upload-rules-link">/plugins/servlet/mimautoescalateplugin/rules?op=preupload</link>
</web-item>
...
pom.xml
...
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
...
<properties>
<jira.version>7.7.1</jira.version>
<amps.version>6.3.15</amps.version>
<plugin.testrunner.version>1.2.3</plugin.testrunner.version>
<atlassian.spring.scanner.version>1.2.13</atlassian.spring.scanner.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<atlassian.template.renderer.version>2.0.0</atlassian.template.renderer.version>
<activeobjects.version>1.5.0</activeobjects.version>
<spring.version>4.2.5.RELEASE</spring.version>
<gson.version>2.3.1</gson.version>
...
</properties>
...
拾取文件并按下上传按钮后,来自 servlet 调试的以下消息出现在日志中:
[INFO] [talledLocalContainer] 2018-05-17 09:00:55,820 DEBUG admin [c.p.j.escalate.ui.RulesServlet] doPost method called.
[INFO] [talledLocalContainer] 2018-05-17 09:00:55,821 DEBUG admin [c.p.j.escalate.ui.RulesServlet] User performing action admin.
[INFO] [talledLocalContainer] 2018-05-17 09:00:55,822 DEBUG admin [c.p.j.escalate.ui.RulesServlet] Updating rules...
[INFO] [talledLocalContainer] 2018-05-17 09:00:55,822 DEBUG admin [c.p.j.escalate.ui.RulesServlet] Request content type: multipart/form-data; boundary=----WebKitFormBoundaryxRnbEsLcgjpzyKWn
[INFO] [talledLocalContainer] 2018-05-17 09:00:55,822 DEBUG admin [c.p.j.escalate.ui.RulesServlet] Request parameterMap size: 1
[INFO] [talledLocalContainer] 2018-05-17 09:00:55,823 DEBUG admin [c.p.j.escalate.ui.RulesServlet] Request parts size: 0
[INFO] [talledLocalContainer] 2018-05-17 09:00:55,823 ERROR admin [c.p.j.escalate.ui.RulesServlet] Error creating escalate rules.
[INFO] [talledLocalContainer] java.lang.NullPointerException
ParameterMap 仅包含来自链接的“op”参数(“.../plugins/servlet/mimautoescalateplugin/rules?op=preupload”)。 request.getParts().size()为 0,所以request.getPart("file")返回null,没有文件上传。似乎没有定义任何形式。
有没有人知道发生了什么或错误在哪里?
提前致谢!!
解决方案
推荐阅读
- python - 对 Python Pandas 中的每一行进行去标记
- database - 如果可能有多个服务器(并且每个服务器都可以有多个线程),如何处理竞争条件
- limit - 批量更新的 Google Sheets API 限制
- c++ - 没有堆分配的 C++ 所有权
- python - Python numpy:从第二个数组中选择性地给定信息对数组求和
- javascript - 滑动窗口 - findLongestSubString(请解释这段代码/答案)
- python - Plotly Dash 中的堆积条形图
- heroku - 提出动画师heroku部署问题
- firebase - 如何在上传文件 Firebase 存储之前选择最接近用户位置的存储桶?(扑)
- amazon-web-services - 我们应该如何在 AWS 无服务器框架中配置 apigateway--> step function proxy?