1.Nginx上传介绍
文件在POST上传到nginx服务器时,nginx会自己将这个文件先保存下来,然后再往后端发送。
在这个过程中,文件会被保存成一个临时文件,待文件传送完成后,nginx向后端(如resin)通知临时文件的文件信息(如上传文件原有的文件名、存在本地磁盘哪个目录下、临时文件名、文件的md5、文件的类型、文件的大小等)。
后端服务拿到这个文件名可以直接读取缓存的文件,进行迁移转码等后续逻辑。
2.安装
下载nginx upload模块
http://www.grid.net.ru/nginx/upload.en.html
tar zxvf nginx_upload_module-2.2.0.tar.gz
在nginx添加该模块
./configure --prefix=/usr/local/nginx --with-pcre=/root/pcre-8.11 --with-http_stub_status_module --with-http_realip_module --add-module=/root/nginx_upload_module-2.2.0 --add-module=/root/masterzen-nginx-upload-progress-module-3d8e105/
3.配置nginx.conf
# Upload form should be submitted to this location
location /upload {
# Pass altered request body to this location
upload_pass @test;
upload_pass_args on;
upload_max_file_size 1m;
# Store files to this directory
# The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
upload_store /tmp 1;
# Allow uploaded files to be read only by user
upload_store_access user:r;
# Set specified fields in request body
upload_set_form_field "${upload_field_name}.name" $upload_file_name;
upload_set_form_field "${upload_field_name}.content_type" $upload_content_type;
upload_set_form_field "${upload_field_name}.path" $upload_tmp_path;
# Inform backend about hash and size of a file
#upload_aggregate_form_field "${upload_field_name}.md5" $upload_file_md5;
upload_aggregate_form_field "${upload_field_name}.crc32" $upload_file_crc32;
upload_aggregate_form_field "${upload_field_name}.size" $upload_file_size;
upload_pass_form_field "^submit$|^test$";
upload_cleanup 400 404 499 500-505;
}
# Pass altered request body to a backend
location @test {
proxy_pass http://resin;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
指定上传文件的大小
keepalive_timeout 200;
client_max_body_size 100m;
二、.resin端程序的接收
1.上传的页面index.html
Test upload选择文件1:
选择文件2:
选择文件3:
2.添加一个Servlet.修改web.xml
upload
com.XXX.servlet.Upload
upload
/upload.so
3.编写Servlet,
将file的信息封装到upFiles的map中。
页面的其他信息(如:test),封装到agrs的map中
package com.XXXX.web.servlet;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.XXXX.model.UpFile;
import com.XXXX.UploadManager;
/**
* @author winston
*
*/
public class Upload extends HttpServlet{
private final Log log = LogFactory.getLog(Upload.class);
private Map upFiles = new HashMap();
private Map agrs = new HashMap();
private ServletInputStream sis = null; //
private byte[] b = new byte[4096]; //
private static String rturl = "http://XXXXXX/ok.html";
public static final String FILE_NAME="filename";
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext application = getServletContext();
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(application);//获取spring的context
UploadManager uploadManager = (UploadManager) wac.getBean("uploadManager");
sis = request.getInputStream();
int a = 0;
int k = 0;
String s = "";
while ((a = sis.readLine(b, 0, b.length)) != -1) {
s = new String(b, 0, a);
if ((k = s.indexOf("name=\"")) != -1) {
String fieldName = s.substring(k + 6, s.length() - 3);
sis.readLine(b, 0, b.length);
StringBuffer fieldValue = new StringBuffer(b.length);
while ((a = sis.readLine(b, 0, b.length)) != -1) {
s = new String(b, 0, a - 2);
if ((b[0] == 45) && (b[1] == 45) && (b[2] == 45)
&& (b[3] == 45) && (b[4] == 45)) {
break;
} else {
fieldValue.append(s);
}
}
if(fieldName.startsWith(FILE_NAME)){
setField(fieldName, fieldValue.toString());
}else{
agrs.put(fieldName, fieldValue.toString());
}
//fields.put(fieldName, fieldValue.toString());
}
}
//业务处理
uploadManager.saveUpload(upFiles, agrs);
response.sendRedirect(rturl);
}
private void setField(String file_name, String file_value){
String[] str = file_name.split("\\.");
UpFile upFile = null;
if(upFiles.containsKey(str[0])){
upFile = upFiles.get(str[0]);
}else{
upFile = new UpFile();
}
String fieldName = str[1];
String value = file_value;
String setMethodName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
try {
Method setMethod = upFile.getClass().getMethod(setMethodName, String.class);
if (value != null) {
setMethod.invoke(upFile, value);
}
} catch (Exception e) {
e.printStackTrace();
log.error(MessageFormat.format("Could not set ''{0}.{1} with value {2}",
upFile, fieldName, value));
}
upFiles.put(str[0], upFile);
}
}
2。对应nginx传递的参数,封装的对象
package com.XXX.model;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
public class UpFile {
private String name;
private String content_type;
private String path;
private String crc32;
private String size;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent_type() {
return content_type;
}
public void setContent_type(String content_type) {
this.content_type = content_type;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getCrc32() {
return crc32;
}
public void setCrc32(String crc32) {
this.crc32 = crc32;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("name", this.name)
.append("content_type", this.content_type)
.append("path", this.path)
.append("crc32", this.crc32)
.append("size", this.size)
.toString();
}
/**
* @see java.lang.Object#equals(Object)
*/
public boolean equals(Object object) {
if (!(object instanceof UpFile)) {
return false;
}
UpFile rhs = (UpFile) object;
return new EqualsBuilder().appendSuper(super.equals(object)).append(
this.content_type, rhs.content_type)
.append(this.size, rhs.size).append(this.path, rhs.path)
.append(this.crc32, rhs.crc32).append(this.name, rhs.name)
.isEquals();
}
/**
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return new HashCodeBuilder(-404694209, 2059458549).appendSuper(
super.hashCode()).append(this.content_type).append(this.size)
.append(this.path).append(this.crc32).append(this.name)
.toHashCode();
}
}
3.业务处理uploadManager就按自己的需求写就可以了
0
顶
0
踩
分享到:
2011-01-05 14:00
浏览 10257
评论
2 楼
yhq1212
2015-08-16
如何禁止NGINX先本地缓存呢
1 楼
zhaoshuli99
2011-01-17
你还搞了个博客,呵呵;
这个upload还行吧,但不能断点续传