1. 程式人生 > >web專案-檔案下載(檔案伺服器-應用伺服器-客戶端)

web專案-檔案下載(檔案伺服器-應用伺服器-客戶端)

檔案的下載一直都是web專案中的常用功能,但是在我們公司專案中,專案上線後單下載功能方面都可以簡單易懂的說分為三個部分,即檔案伺服器、應用伺服器和客戶端,而我們在上傳的時候都是將上傳儲存到檔案伺服器(也可以俗稱網路伺服器),而在資料庫中儲存的只是檔案在檔案伺服器上的地址,類似於“http://182.168.1.1/group1/M00/00/73/wKgBDVoGbFWACZ_HAlZxO4o_Y24986.doc”這樣的欄位,在下載的時候只是獲取到了資料庫中儲存的地址資訊,然後到檔案伺服器上去找,然後下載。

網上大多的下載方法都是採用servlet方法下載,而我說的這種下載方式可能和網上多數下載方法不同(也或許是我沒有發現更多類似的吧^_^),當時在我做的時候碰到了很多問題,也都在網上找了很多的下載方法,但都是從檔案伺服器下載到應用伺服器,客戶端網頁並沒有提示檔案下載儲存等資訊,也有很多是從應用伺服器下載到客戶端,但是一般都是不把檔案上傳儲存到應用伺服器的專案裡面的,因為對造成專案過於龐大,也會增加應用伺服器的負荷,所以在這裡我總結一下我的下載方法,

整個下載過程是這樣的:

從檔案伺服器拿到檔案---下載到應用伺服器---最後再下載到客戶端

我的方法程式碼如下:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.xk.util.PropertyUtil;






@Controller
@RequestMapping(value = "/DownloadServlet", produces = "text/html;charset=utf-8")
public class DownloadController extends HttpServlet {


	private static final long serialVersionUID = 1L;
	/**
	 * 獲取伺服器上的檔案下載到客戶端
	 * @param filePath
	 * @param request
	 * @param response
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping(value = "/Download.do")
	protected @ResponseBody void doGet(String filePath,HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());  

		String file_path = PropertyUtil.getProperty("file_path");
		File savePath = new File(file_path+date);
		if (!savePath.exists()) {
			savePath.mkdir();   
		}  
		String[] urlname = filePath.split("/");  
		int len = urlname.length-1;  
		String uname = urlname[len];
		try {  
			File file = new File(savePath+"/"+uname);
			if(file!=null && !file.exists()){  
				file.createNewFile();  
			}  
			OutputStream oputstream = new FileOutputStream(file);  
			URL url = new URL(filePath);  
			HttpURLConnection uc = (HttpURLConnection) url.openConnection();  
			uc.setDoInput(true); 
			uc.connect();  
			InputStream iputstream = uc.getInputStream();  
			byte[] buffer = new byte[4*1024];
			int byteRead = -1;     
			while((byteRead=(iputstream.read(buffer)))!= -1){  
				oputstream.write(buffer, 0, byteRead);  
			}  
			 // 取得檔案的字尾名。
			String ext = uname.substring(uname.lastIndexOf(".") + 1).toUpperCase();

			
			oputstream.flush();    
			iputstream.close();  
			oputstream.close();  
			
			
	        InputStream inStream = new FileInputStream(savePath+"/"+uname);
	        InputStream fis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer2 = new byte[fis.available()];
            fis.read(buffer2);
            fis.close();
            response.reset();
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(uname.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            
            byte[] b = new byte[100];
            int len1;
            while ((len1 = inStream.read(b)) > 0)
                response.getOutputStream().write(b, 0, len1);
            inStream.close();
		
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
            file.delete();
            savePath.delete();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
	}
}

可能新手們會問一個問題,那就是檔案從檔案伺服器下載到應用伺服器上儲存在什麼地方?

String file_path = PropertyUtil.getProperty("file_path");
這個就是我獲取到的配置檔案中的在應用伺服器上檔案要儲存的地址,當然,這裡我還生成了一個date作為資料夾,但是後來還是覺得會增加應用伺服器的負荷,所以後來又經過改進,增加了檔案刪除方法,在檔案下載到客戶端後,對應用伺服器上的檔案進行刪除操作。即
savePath.delete();
前臺呼叫下載方法的時候,需要傳一個引數,那就是filePath,也就是從資料庫獲取到的下載地址。

其實這裡還有一個待改進的地方,就是下載後的檔案的檔名是伺服器生成的,所以如果大家有高標準要求還可以從資料庫獲取更多的資訊,對下載檔案進行操作。

這裡進行一下更多的解釋(當然都是為了能幫助更多的新手,我相信更多的程式設計師是能看的懂程式碼的,新手們加油喲!)

oputstream.flush();    
			iputstream.close();  
			oputstream.close();
程式碼中上面這些關閉流之前的,都是從檔案伺服器下載到應用伺服器的,後面的才是從應用伺服器下載到客戶端的。

切記:

記得關閉流!!!

新手在這裡獻醜啦!希望大家取得更多的進步!!