Jim*_*Jim 5 java pdf coldfusion post unit-testing
在我的问题之前有一点历史,我发布了一个关于使用HTML5的multipart/form-data将多个文件上传到coldfusion的问题.它工作得很漂亮. 你能否从CF10编译器中看到代码?
我们的客户端终于要求对我放在一起的RESTful函数进行一些单元测试,并且我已经完成了很多工作,但是我已经遇到了上面设计的massUpload函数的障碍.
对于长期问题,请记下与问题相关的问题.
这是有问题的代码:
单元测试代码:
//Outside class calling sendHTTPrequest
HashMap<String,String> map = new HashMap<String,String>();
HashMap<String,File> getFiles = getFirstFileList();
map.put("testMethod", "massUploadTest");
map.put("method", "massUpload");
map.put("valueString1", valueString1);
map.put("valueString2", valueString2);
map.put("valueNumeric3", valueNumeric3);
map.put("valueBoolean4", valueBoolean4);
map.put("valueString5", valueString5);
map.put("valueBoolean6", valueBoolean6);
map.put("valueString7", valueString7);
try {
sendHTTPrequest(map, getFiles);
} catch(RuntimeException e) {
throw new RuntimeException("Fatal error in massUpload\n"
+ e.getMessage());
}
//End Call class code
Run Code Online (Sandbox Code Playgroud)
Coldfusion功能:
<cffunction name="massUpload" access="remote" returntype="string">
<cfargument name="valueString1" type="string" required="false">
<cfargument name="valueString2" type="string" required="false">
<cfargument name="valueNumeric3" type="numeric" required="false" default=0>
<cfargument name="valueBoolean4" type="boolean" required="true" default="false">
<cfargument name="valueString5" type="string" required="false">
<cfargument name="valueBoolean6" type="boolean" required="false" default="true">
<cfargument name="valueString7" type="string" required="true">
<!--- massUpload code --->
</cffunction>
Run Code Online (Sandbox Code Playgroud)
所以这是造成重大问题的代码.我已经尝试了不同的方法来使POST工作,所以显然代码有问题.我试图这样做而不下载多个软件/库,但如果没有别的办法,那么我会做出必要的安排.否则,我们很乐意使用标准Java库来完成这项工作.
功能码:
//sendHTTPrequest method code
protected static final String BASE_URI = "<webaddress>/rest.cfc";
protected static final String CHARSET = "UTF-8";
protected String response;
protected int status;
protected String statusMessage;
protected void sendHTTPrequest(Map<String,String> map, Map<String, File> fileList) {
Set<String> keys = map.keySet();
status = 0;
response = null;
String boundary = "----" + System.currentTimeMillis();
try {
URL_CONNECTION = BASE_URL.openConnection();
HTTP_CONNECTION = (HttpURLConnection) (URL_CONNECTION);
//Set the request headers
HTTP_CONNECTION.setRequestMethod("POST");
URL_CONNECTION.setRequestProperty("Accept-Charset", CHARSET);
URL_CONNECTION.setRequestProperty("Content-type", "multipart/form-data; boundary=" + boundary);
//Set up a post request
URL_CONNECTION.setDoOutput(true);
OutputStream output = URL_CONNECTION.getOutputStream();
ByteArrayOutputStream bOutput = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, CHARSET), true);
for(String key : keys) {
writer.write("--" + boundary);
writer.write(lineFeed);
writer.write("Content-Disposition: form-data; name=\"" + key + "\"");
writer.write(lineFeed);
writer.write(lineFeed);
writer.write(map.get(key));
writer.write(lineFeed);
}
FileInputStream inputStream;
for(Map.Entry<String, File> entry : fileList.entrySet()){
String name = entry.getKey();
writer.write("--" + boundary);
writer.write(lineFeed);
writer.write("Content-Disposition: form-data; "
+ "name=\"allfiles\"; filename=\"" + name + "\"");
writer.write(lineFeed);
String contentType = URLConnection.guessContentTypeFromName(name);
writer.write("Content-Type: " + contentType);
writer.write(lineFeed);
writer.write("Content-Transfer-Encoding: binary");
writer.write(lineFeed);
writer.write("Content-Id: <" + boundary + ">");
writer.write(lineFeed);
writer.write(lineFeed);
File temp = entry.getValue();
byte[] buffer = FileUtils.readFileToByteArray(temp);
output.write(buffer, 0, buffer.length);
output.flush();
writer.write(lineFeed);
}
writer.write("--" + boundary + "--");
writer.write(lineFeed);
writer.flush();
writer.close();
status = HTTP_CONNECTION.getResponseCode();
statusMessage = HTTP_CONNECTION.getResponseMessage();
if(status == SUCCESS) {
response = IOUtils.toString(URL_CONNECTION.getInputStream(), URL_CONNECTION.getContentEncoding());
}
System.out.println("Finished test " + map.get("testMethod") + " Status: " + status);
System.out.println("Response: " + response);
HTTP_CONNECTION.disconnect();
} catch(UnknownServiceException use) {
throw new RuntimeException("Protocol for the output is not supported");
} catch(IOException ioe) {
throw new RuntimeException("Unable to create the output stream");
}
}
//End sendHTTPrequest method code
Run Code Online (Sandbox Code Playgroud)
我在输出中看到status,response和statusMessage,我得到500错误,null,内部服务器错误.
在Coldfusion服务器上看,我看到:
SEVERE: Servlet.service() for servlet [CFCServlet] in context with path [/] threw exception
java.io.IOException: Corrupt form data: no leading boundary: %PDF-1.4 != ------1429222349902
at com.oreilly.servlet.multipart.MultipartParser.<init>(MultipartParser.java:182)
...
Run Code Online (Sandbox Code Playgroud)
massUpload可以处理不同类型的文件,但专门针对PDF.因此,单元测试需要能够将不同的文件类型发送到massUpload,而不仅仅是PDF.
任何对这个问题的见解都会受到欢迎.谢谢.
(来自评论)
您是否使用数据包嗅探器来查看上面实际生成的内容?
尝试在写入文件字节之前刷新写入器:
...
byte[] buffer = FileUtils.readFileToByteArray(temp);
writer.flush(); // flush stream here
output.write(buffer, 0, buffer.length);
...
Run Code Online (Sandbox Code Playgroud)
更新:
只是澄清一下,最初错误的原因是,即使代码创建了一个 PrintWriter ,但在调用autoFlush=true时它仍然不会自动将文本保存到底层 OutputStream 中。write()该autoFlush设置仅影响这些方法:
autoFlush - 如果为 true,则
println、printf或format方法将[自动]刷新输出缓冲区
因此,代码将文件内容写入边界标记之前的流,从而创建无效的 HTTP POST。因此出现了 500 错误。您可以使用 Fiddler 等包嗅探器来验证这一点:
原件-(无效):
POST http://localhost:8888/test.cfm HTTP/1.1
Accept-Charset: UTF-8
Content-Type: multipart/form-data; boundary=14cd4c75e24
...
Content-Length: 65570
%PDF-1.4
%
2 0 obj <</Type/XObject/ColorSpace/DeviceGray/Subtype/Image/BitsPerComponent 8/Width 612/Length 11876/Height 792/Filter/FlateDecode>>stream
... more binary
--14cd4c75e24
Content-Disposition: form-data; name="allfiles"; filename="file0.pdf"
Content-Type: application/pdf
Content-Transfer-Encoding: binary
Content-Id: <14cd4c75e24>
--14cd4c75e24--
Run Code Online (Sandbox Code Playgroud)
解决方案是在添加文件内容之前刷新写入器。这可确保边界标记添加到正确的位置,从而生成的 POST 内容有效。
新代码(有效)
POST http://localhost:8888/test.cfm HTTP/1.1
Accept-Charset: UTF-8
Content-Type: multipart/form-data; boundary=14cd4c91d29
...
Content-Length: 65570
--14cd4c91d29
Content-Disposition: form-data; name="allfiles"; filename="file0.pdf"
Content-Type: application/pdf
Content-Transfer-Encoding: binary
Content-Id: <14cd4c91d29>
%PDF-1.4
%
2 0 obj <</Type/XObject/ColorSpace/DeviceGray/Subtype/Image/BitsPerComponent 8/Width 612/Length 11876/Height 792/Filter/FlateDecode>>stream
...
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我相信Content-Id一定是独一无二的。因此,对于 Content-Id 值来说,“边界”可能不是一个好的选择。