httpcomponentClient upload file

http://radomirml.com/2009/02/13/file-upload-with-httpcomponents-successor-of-commons-httpclient




File upload with HttpComponents Client 4.0 (successor of Commons HttpClient 3.x)

by radomir on February 13, 2009

Background: I’m working on an application that should be able to integrate with various issue trackers (JIRA, Bugzilla, etc.) First I tried using the latest stable branch of Apache Commons HttpClient 3.1 but soon faced problems as JIRA (running on Tomcat) was not able to extract all parameters I was sending with “multipart/form-data” encoding. I’ve found similar problems reports on the Internet but no solution. So, I’ve decided to try the latest HttpComponents Client (4.0-beta2, while core library was 4.0-beta3 at the time of writing) which came with new problems but my form submission and file upload worked at the end. I summarize my experience here.

As soon as I downloaded HttpComponents Client I realized why they changed the name from Commons HttpClient. This is a completely new API! If you already have code that relies on Commons HttpClient you can not easily switch jar file and make some minor changes. Fortunatelly, HttpComponents use different packages so you should be able to keep your HttpClient code and have both versions coexist in the same application without conflicts. However, I can’t resist to mention that HttpComponents API looks to me a bit over-engineered and so low level that it hurts. (But maybe it’s just me being spoiled after a month on Groovy.)

HttpComponents Client still doesn’t have an appropriate documentation and I could not find a single example of file upload that worked for me. So, after mingling my existing code and code from HttpComponents test cases, I’ve finally made a first version that was able to upload file and here’s somewhat simplified version of it:

public void testUpload() throws Exception {
	HttpClient httpclient = new DefaultHttpClient();
	HttpPost httppost = new HttpPost(myUploadUrl);

	MultipartEntity reqEntity = new MultipartEntity(
		HttpMultipartMode.BROWSER_COMPATIBLE);

	reqEntity.addPart("string_field",
		new StringBody("field value"));

	FileBody bin = new FileBody(
		new File("/foo/bar/test.png"));
	reqEntity.addPart("attachment_field", bin );

	httppost.setEntity(reqEntity);

	System.out.println("executing request " + httppost.getRequestLine());
	HttpResponse response = httpclient.execute(httppost);
	HttpEntity resEntity = response.getEntity();

	if (resEntity != null) {
		String page = EntityUtils.toString(resEntity);
		System.out.println("PAGE :" + page);
	}
}

I omit package imports in the example above but I’m sure you’ll manage without it. Notice use of HttpMultipartMode.BROWSER_COMPATIBLE parameter in line 6. It was crucial for me as upload didn’t work when I used default constructor for MultipartEntity (that initializes entity for the strict multipart mode). With hope that code above is all what’s needed, I made a small change (replacing lines 11-13 above) to upload image from byte array instead from file:

	reqEntity.addPart("attachment_field",
		new InputStreamBody(
			new ByteArrayInputStream(imageBytes),
			"image/png", "test.png"));

Surprisingly, this change broke my upload! Again, documentation and googling on this topic didn’t give me any clue on what could be wrong. So, I plunged into HttpComponents source code and found that the major different between the InputStreamBody and FileBody was that method getContentLength() of the former was returning -1 (which is somewhat logical but again…). As I already had image as a byte array, content length was known to me. So, I extended InputStreamBody class as follows:

class InputStreamKnownSizeBody extends InputStreamBody {
	private int lenght;

	public InputStreamKnownSizeBody(
			final InputStream in, final int lenght,
			final String mimeType, final String filename) {
		super(in, mimeType, filename);
		this.lenght = lenght;
	}

	@Override
	public long getContentLength() {
		return this.lenght;
	}
}

Now I could use my InputStreamKnownSizeBody class to upload any in-memory file:

	reqEntity.addPart("attachment_field",
		new InputStreamKnownSizeBody(
			new ByteArrayInputStream(imageBytes),
			imageBytes.length, "image/png", "test.png"));

At the end, although I’m not delighted with complexities of HttpComponents, it worked for me at the end and I resolved file upload issues I experienced with Commons HttpClient. I hope this post will be of help to someone.

EDIT (2010-10-20): At least few people were struggling with requirement for the MIME library (see bellow discussion). I’ve personally switched to the 4.1 Alpha 2 (the latest version at the time of writing) which removes dependency on org.apache.james.mime4j and comes with own httpmime-4.1-xxx.jar library.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Spring Boot 和 Vue 中实现文件上传,可以按照以下步骤进行: 1. 在 Vue 中创建一个文件上传表单,代码如下: ``` <template> <div> <form> <input type="file" ref="fileInput"> <button type="button" @click="uploadFile">上传</button> </form> </div> </template> <script> export default { methods: { uploadFile() { let file = this.$refs.fileInput.files[0]; let formData = new FormData(); formData.append("file", file); // 发送文件到后端 } } } </script> ``` 2. 在 Spring Boot 中创建一个文件上传接口,代码如下: ``` @RestController public class FileUploadController { @PostMapping("/upload") public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file) { try { String fileName = file.getOriginalFilename(); Path path = Paths.get("/uploads/" + fileName); Files.write(path, file.getBytes()); return new ResponseEntity<>("File uploaded successfully", HttpStatus.OK); } catch (IOException e) { e.printStackTrace(); return new ResponseEntity<>("Failed to upload file", HttpStatus.INTERNAL_SERVER_ERROR); } } } ``` 3. 在 Vue 中使用 `axios` 发送文件到后端,代码如下: ``` <template> <div> <form> <input type="file" ref="fileInput"> <button type="button" @click="uploadFile">上传</button> </form> </div> </template> <script> import axios from 'axios'; export default { methods: { uploadFile() { let file = this.$refs.fileInput.files[0]; let formData = new FormData(); formData.append("file", file); axios.post("/upload", formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(response => { console.log(response.data); }).catch(error => { console.log(error); }); } } } </script> ``` 以上就是在 Spring Boot 和 Vue 中实现文件上传的步骤。注意,在 Spring Boot 中需要在 `application.properties` 中配置文件上传路径,例如: ``` spring.servlet.multipart.enabled=true spring.servlet.multipart.file-size-threshold=2KB spring.servlet.multipart.max-file-size=200MB spring.servlet.multipart.max-request-size=215MB spring.servlet.multipart.location=/uploads/ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值