servlet formフォームからコミットされたファイルを取得
17524 ワード
知らず知らずのうちに、私はすでにスタック全体の道に向かっているような気がします.この2、3日、バックエンドで転送されたファイルデータを受信することを学びました.レベルが多すぎるので、servletを使ってデータを受信するつもりです.このブログは、アップロードされたファイルの取得方法、htmlプロトコルの内容からファイルの取得方法、Apache Commons FileUploadソースコードの読み取り方法の理解を浅く深く記録しています.
How
html form formタグに属性enctype="multipart/form-data" を追加
servlet apiでファイル内容を取得する
enctype="multipart/form-data"属性を含むフォームからコミットされたデータは、サーブレットRequest.getParameterメソッドではパラメータを取得できません.次の手順でパラメータを取得します.1、サーブレット類に注釈を付ける@MultipartConfig 2、サーブレットRequest.getPartメソッドを使用してPartオブジェクトを取得します.Partオブジェクトは対応するあなたのフォームの各inputです.
欠点:渡されたフォームのvalueを取得したい場合は、PartはInputStream getInputStream()throws IOExceptionのみを提供してくれます.方法は、普通のテキストタイプに対して、私たちは自分で処理しなければなりません.
Apache Commons FileUploadでファイル内容を取得する
まずApache Commons FileUpload依存を追加します.
上記のコードのように、取得したFileItemは対応するフォームのinputであり、FileItemによってストリームや値を取得できるなど、オリジナルのservlet apiよりも便利です.
Apache Commons FileUpload非file属性文字化を取得
FileItem.getStringは、フォームから渡された属性値を取得する方法であり、デフォルトではISO-8859-1で復号されます.このメソッドには、String getString(String encoding)throws UnsupportedEncodingExceptionがリロードされます.を選択して設定できます.
に注意
formフォームにenctype="multipart/form-data"(またはmultipart/mixedなど似たような)属性が追加されていない場合は、サーブレットRequest.getParameterを使用してパラメータを取得します.上記の2つの方法で処理することはできません.そうしないと、エラーが発生します.
formフォームにenctype="multipart/form-data"(またはmultipart/mixedなど類似の)属性が追加されている場合は、サーブレットRequest.getParameterメソッドでは値が取得できないため、上記の2つの方法または類似の方法で要求パラメータを処理する必要があります.
したがって、formフォームにenctype="multipart/form-data"(またはmultipart/mixedなど似たような)属性が追加されているかどうかについては、異なる処理があります.もちろん、これはもともと既知です.formフォームは私たちが自分で書いたからです.伝達されたhttpリクエストヘッダから判断することもできますが、次のブログでは、httpリクエストが送信したデータの中でどのように異なるのかを提示します.Apache Commons FileUploadライブラリは、次のような簡単な方法で判断できます.
why
socketは簡単なwebサーバを実現し、httpリクエスト情報を表示することができます.これは私が以前書いたブログで、httpリクエストが送信した内容を直感的に観察することができます.
enctype="multipart/form-data":この属性はpostデータの場合、どのような形式でデータを符号化するかに影響します.このプロパティのデフォルト値はアプリケーション/x-www-form-urlencodedです.post,enctypeがこの2つの値である場合についてのみ議論する.
enctype=”application/x-www-form-urlencoded”
enctype=”multipart/form-data”
区別する
ここでは、リクエストヘッダのContent-Typeプロパティとリクエストボディの2つに注意する必要があります.リクエストヘッダのContent-Type属性は異なり,サーバ側はこの属性からリクエストパラメータをそのように処理すると判断できる.Content-Typeがmultipart/form-dataの場合、boundary=—-WebKitFormBoundary 2 vmXA 3 pgPdCoiZjvという値があります.これは、要求体の異なる属性を区別します. enctype="application/x-www-form-urlencoded"の場合、リクエストボディにはurlencodedが2層にパッチされたクエリー文字列があります.enctype="multipart/form-data"の場合、フォームはboundaryによって異なる部分に分けられ、各部分にはヘッダーとデータが含まれています.上記の例のように.
解析
getリクエストまたはpostでenctype="アプリケーション/x-www-form-urlencoded"の場合、サーブレットRequest.getParameterメソッドをそのまま使用するとパラメータが得られますが、ここでは説明しません.
postかつenctype="multipart/form-data"の場合、データはリクエスト体の中にあり、リクエスト体のフォーマットも知っています.このフォーマットに従って必要なデータを解析します.まず体力を要求する内容が得られ,サーブレットRequest.getInputStreamメソッドが返す入力ストリームは体力を要求する内容全体を含むことが分かった.
上記のpostリクエスト体データを本当に解析するのか、それとも複雑なことなのか、責任ある(怠け者)態度で自分で書くことはありません.次の内容はApache Commons FileUploadソースコードを読むことの理解です.
Apache Commons FileUpload理解
コードが少し多いので、貼らないで、私の理解を書いてください.1、要求体をまずFileItemIteratorに解析し、このオブジェクトは反復器であり、すべてのFileItemStreamオブジェクトを取得することができ、FileItemStreamオブジェクトは伝達されたinputの内容に対応することができ、fieldName、ストリームなどのデータを取得することができる. 2、FileItemIteratorを巡り、FileItemStreamによってFileItemが生成され、本当に生成されたのはFileItemのサブクラスDiskFileItemである. 3、解析時にこのような2層の構造を用いて拡張を容易にするため、FileItemStreamオブジェクトは元のデータを表すことができ、それによってFileItemを生成することができ、現在生成されているのはDiskFileItemであり、以降データベースでキャッシュできるFileItemも知られていない.公式文書にはFileItemStreamを使ってデータを取得するというストリーミングAPI. という紹介もあります4、メモリを節約するために、DiskFileItemはその内容の大きさに応じて、そのデータをファイルシステムにキャッシュするかどうかを決定します.
リファレンス
HTMLタグのenctypeプロパティsocketは、httpリクエスト情報FileUpload–Using FileUploadを表示する簡単なWebサーバを実現します.
How
html form
<form action="../form_ajax" method="post" enctype="multipart/form-data">
:<input type="text" name="username"/><br/>
<br/>
:<input type="file" name="myfile"/><br/>
<input type="submit" value="submit"/><br/>
form>
servlet apiでファイル内容を取得する
@MultipartConfig
public class FileUpload1Servlet extends HttpServlet {
private static Logger LOGGER = Logger.getLogger(FileUpload1Servlet.class);
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//
// Servlet @MultipartConfig
// part name
Part part = req.getPart("myfile");
//Servlet3 ,
//
String fileName = part.getSubmittedFileName();
//
InputStream inputStream = part.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer sb = new StringBuffer();
String line = br.readLine();
while(line != null){
sb.append("
").append(line);
line = br.readLine();
}
LOGGER.info("content:"+sb.toString());
PrintWriter printWriter = resp.getWriter();
printWriter.print(" , 。");
printWriter.flush();
printWriter.close();
}
}
enctype="multipart/form-data"属性を含むフォームからコミットされたデータは、サーブレットRequest.getParameterメソッドではパラメータを取得できません.次の手順でパラメータを取得します.
欠点:
Apache Commons FileUploadでファイル内容を取得する
まずApache Commons FileUpload依存を追加します.
public class FileUpload2Servlet extends HttpServlet {
private static Logger LOGGER = Logger.getLogger(FileUpload2Servlet.class);
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Configure a repository (to ensure a secure temp location is used)
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
try {
// Parse the request
List items = upload.parseRequest(req);
// Process the uploaded items
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = iter.next();
if (item.isFormField()) {
processFormField(item);
} else {
processUploadedFile(item);
}
}
} catch (Exception e) {
e.printStackTrace();
}
PrintWriter printWriter = resp.getWriter();
printWriter.print(" , 。");
printWriter.flush();
printWriter.close();
}
private void processFormField(FileItem item) {
}
private void processUploadedFile(FileItem item) {
}
}
上記のコードのように、取得したFileItemは対応するフォームのinputであり、FileItemによってストリームや値を取得できるなど、オリジナルのservlet apiよりも便利です.
Apache Commons FileUpload非file属性文字化を取得
FileItem.getStringは、フォームから渡された属性値を取得する方法であり、デフォルトではISO-8859-1で復号されます.このメソッドには、String getString(String encoding)throws UnsupportedEncodingExceptionがリロードされます.を選択して設定できます.
に注意
formフォームにenctype="multipart/form-data"(またはmultipart/mixedなど似たような)属性が追加されていない場合は、サーブレットRequest.getParameterを使用してパラメータを取得します.上記の2つの方法で処理することはできません.そうしないと、エラーが発生します.
formフォームにenctype="multipart/form-data"(またはmultipart/mixedなど類似の)属性が追加されている場合は、サーブレットRequest.getParameterメソッドでは値が取得できないため、上記の2つの方法または類似の方法で要求パラメータを処理する必要があります.
したがって、formフォームにenctype="multipart/form-data"(またはmultipart/mixedなど似たような)属性が追加されているかどうかについては、異なる処理があります.もちろん、これはもともと既知です.formフォームは私たちが自分で書いたからです.伝達されたhttpリクエストヘッダから判断することもできますが、次のブログでは、httpリクエストが送信したデータの中でどのように異なるのかを提示します.Apache Commons FileUploadライブラリは、次のような簡単な方法で判断できます.
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
why
socketは簡単なwebサーバを実現し、httpリクエスト情報を表示することができます.これは私が以前書いたブログで、httpリクエストが送信した内容を直感的に観察することができます.
enctype="multipart/form-data":この属性はpostデータの場合、どのような形式でデータを符号化するかに影響します.このプロパティのデフォルト値はアプリケーション/x-www-form-urlencodedです.post,enctypeがこの2つの値である場合についてのみ議論する.
enctype=”application/x-www-form-urlencoded”
POST / HTTP/1.1
Host: 127.0.0.1:8000
Connection: keep-alive
Content-Length: 44
Cache-Control: max-age=0
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://localhost:8080/jquery/jquery_easy_ui_demo/index2.html?
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: _ga=GA1.1.2113425928.1460981708
username=%E5%BC%A0%E4%B8%89&myfile=test1.sql
enctype=”multipart/form-data”
POST / HTTP/1.1
Host: 127.0.0.1:8000
Connection: keep-alive
Content-Length: 1043
Cache-Control: max-age=0
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2vmXA3pgPdCoiZjv
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://localhost:8080/jquery/jquery_easy_ui_demo/index2.html?
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: _ga=GA1.1.2113425928.1460981708
------WebKitFormBoundary2vmXA3pgPdCoiZjv
Content-Disposition: form-data; name="username"
------WebKitFormBoundary2vmXA3pgPdCoiZjv
Content-Disposition: form-data; name="myfile"; filename="test1.sql"
Content-Type: application/octet-stream
/*
Navicat MySQL Data Transfer
Source Server : localhost
Source Server Version : 50716
Source Host : localhost
Source Database : test1
Target Server Version : 50716
File Encoding : utf-8
Date: 11/18/2016 00:54:30 AM
*/
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `obj1`
-- ----------------------------
DROP TABLE IF EXISTS `obj1`;
CREATE TABLE `obj1` (
`name` varchar(20) NOT NULL,
`id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `obj1`
-- ----------------------------
BEGIN;
INSERT INTO `obj1` VALUES (' ', '1');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
------WebKitFormBoundary2vmXA3pgPdCoiZjv--
区別する
ここでは、リクエストヘッダのContent-Typeプロパティとリクエストボディの2つに注意する必要があります.
解析
getリクエストまたはpostでenctype="アプリケーション/x-www-form-urlencoded"の場合、サーブレットRequest.getParameterメソッドをそのまま使用するとパラメータが得られますが、ここでは説明しません.
postかつenctype="multipart/form-data"の場合、データはリクエスト体の中にあり、リクエスト体のフォーマットも知っています.このフォーマットに従って必要なデータを解析します.まず体力を要求する内容が得られ,サーブレットRequest.getInputStreamメソッドが返す入力ストリームは体力を要求する内容全体を含むことが分かった.
上記のpostリクエスト体データを本当に解析するのか、それとも複雑なことなのか、責任ある(怠け者)態度で自分で書くことはありません.次の内容はApache Commons FileUploadソースコードを読むことの理解です.
Apache Commons FileUpload理解
コードが少し多いので、貼らないで、私の理解を書いてください.
➜ jquery pwd
/Users/mabinbin/Library/Caches/IntelliJIdea2016.1/tomcat/Unnamed_blog_backend/work/Catalina/localhost/jquery
➜ jquery ls -lh
total 249792
-rw-r--r-- 1 mabinbin staff 122M 4 26 14:18 upload_08e39bf7_614a_4684_aee1_6d44138ff8f4_00000001.tmp
リファレンス
HTMLタグのenctypeプロパティsocketは、httpリクエスト情報FileUpload–Using FileUploadを表示する簡単なWebサーバを実現します.